首页|社区论坛|iTePub书库|在线阅读|电图引擎|技术文档|图书查询|光盘刻录 |

返回首页 我的控制台 会员登陆 免费注册 最后更新 高级搜索 我要投稿 退出登陆 联系我们
操作系统
计算机应用技术
解决方案
精彩书评
开发语言
认证考试
软件工程
数据库
算法与数据结构
网络技术与安全
网站制作
移动通信
电子图书籍下载:会员文档首页 / 操作系统 / linux / Linux嵌入式 / uClinux上的应用程序设计-3
uClinux上的应用程序设计-3
2004-11-04    Luojia, Tsinghua       点击: 2011
uClinux上的应用程序设计-3

3 高效的程序开发

   总的来说,在uClinux上的开发和标准Linux还是很类似的。通常可以按照下面的步骤去设计和调试:

  1. 建立基于以太网的开发环境;
  2. 如果所设计的程序和硬件的关联不大,那么一定要在标准Linux上先编译和调试通过。灵活地使用gcc和gdb将大大节省时间;
  3. 将x86上的GCC编译好的应用程序用交叉编译工具来编译;如果编译时发现错误,那么很可能存在以下问题:
    • 交叉编译器或库文件的路径不正确;最彻底的解决办法是重新装一次编译器;
    • 遇到库不支持的函数;此时需要自己把函数的实现做成另外一个库供应用程序使用。如果是uClinux本身不支持的调用,那么就需要改写代码了。
    • C++的一些写法不太标准,需要修改;
  4. 通过网络(nfsmount)运行交叉编译成功的应用程序;
  5. 如果程序工作初步正常,那么就可以进一步在板子上测试了;否则,需做修改重新编译,尤其要检查与uClinux的内存特性有关的代码。
 

   如果程序较小,设计时就可以比较灵活。如果是一个比较庞大的工程,那么,建立一个好的编译环境非常重要。下面,给出一个较为复杂的工程中所建立的一系列编译文件例子,用好它们可以提高效率。

   例如,在编译x86平台上的程序时,可以这样输入:

   >make config

   出现提示:

   Target Platform Selection

   Choose a Vendor/Product combination.

   Vendor/Product [Intel/i386| Motorola/M5307C3]

   如果我们输入i386,那么就可以编译出PC上运行的程序;而输入M5307C3,就可以编译出uClinux上运行的程序。这对于经常需要在标准Linux和uClinux之间进行交叉编译和查找错误的程序来说非常方便。 

   首先,建立图 2所示的整个工程目录结构。 

图 2 整个工程的目录结构

   在config中,存放一些编译有关的配置文件;src目录下,按照各个程序模块分别创建一个目录。

   在Project目录下,是整个工程的Makefile文件,如下:

    ###########################################################

    #

    # Makefile – Whole Project makefile.

    #

    # Copyright (c) 2001-2002, Tsinghua MAC

    #

    ###########################################################

    #

    # Get the core stuff worked out

    # 

    ROOT_DIR = $(shell pwd)

    SRC_DIR = $(ROOT_DIR)/src

    CONFIG_DIR = $(ROOT_DIR)/config

    SCRIPTS_DIR = $(ROOT_DIR)/scripts 

    CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \

            else if [ -x /bin/bash ]; then echo /bin/bash; \

            else echo sh; fi ; fi)

    TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi) 

    HPATH    = $(TOPDIR)/include

    FINDHPATH = $(HPATH)/asm $(HPATH)/linux $(HPATH)/scsi $(HPATH)/net 

    export ROOT_DIR SRC_DIR CONFIG_DIR SCRIPTS_DIR HPATH FINDHPATH 

    ###########################################################

    # normal make targets

    #

    #

    .PHONY: all

    all:

          $(MAKE) -C $(SRC_DIR) all

    ########################################################### 

    #

    # Config stuff,  we recall ourselves to load the new config.arch before

    # running the kernel and other config scripts

    #

    .PHONY: config

    config: $(CONFIG_DIR)/config.in

          cd $(CONFIG_DIR); $(CONFIG_SHELL) $(SCRIPTS_DIR)/Configure $(CONFIG_DIR)/config.in

          @rm -f $(SRC_DIR)/arch.config

          @if egrep "^CONFIG_DEFAULTS_INTEL_I386" $(CONFIG_DIR)/.config > /dev/null; then \

                 ln -s "$(CONFIG_DIR)/arch.i386" $(SRC_DIR)/arch.config; \

           fi

          @if egrep "^CONFIG_DEFAULTS_MOTOROLA_M5272C3" $(CONFIG_DIR)/.config > /dev/null; then \

                 ln -s "$(CONFIG_DIR)/arch.m68k" $(SRC_DIR)/arch.config; \

           fi

          @echo "#This dir.config file is automaticly generated by make config!" > $(SRC_DIR)/dir.config

          @echo "ROOT_DIR="$(ROOT_DIR) >> $(SRC_DIR)/dir.config

          @echo "CONFIG_DIR="$(CONFIG_DIR) >> $(SRC_DIR)/dir.config

          @echo "SRC_DIR="$(SRC_DIR) >> $(SRC_DIR)/dir.config

          @echo "SCRIPTS_DIR="$(SCRIPTS_DIR) >> $(SRC_DIR)/dir.config

          @echo "HPATH="$(HPATH) >> $(SRC_DIR)/dir.config

          @echo "FINDPATH="$(FINDPATH) >> $(SRC_DIR)/dir.config 

    ###########################################################

    #

    # normal make dependancy

    #

    #

    .PHONY: dep

    dep:

          $(MAKE) -C $(SRC_DIR) dep 

    # This one removes all executables from the tree and forces their relinking

    clean:

          $(MAKE) -C $(SRC_DIR) clean 

    test:

          $(MAKE) -C $(SRC_DIR) test 

    run:

          $(MAKE) -C $(SRC_DIR) run 

    config_error:

          @echo "*************************************************"

          @echo "You have not run make config."

          @echo "The build sequence for this source tree is:"

          @echo "1. 'make config' or 'make xconfig'"

          @echo "2. 'make dep'"

          @echo "3. 'make'"

          @echo "*************************************************"

          @exit 1

    ########################################################### 

   src目录下的Makefile文件,如下: 

    VERSION = 2

    PATCHLEVEL = 0

    SUBLEVEL = 39

    UCRELEASE = uc2 

    .EXPORT_ALL_VARIABLES: 

    CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \

            else if [ -x /bin/bash ]; then echo /bin/bash; \

            else echo sh; fi ; fi)

    TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi) 

    TARGET = ESGateway 

    all: $(TARGET) 

    # Include the make variables (CC, etc...)

    # 

    SUBDIRS  =  public serial packet cal xml fifo main interface 

    $(TARGET):

          @set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i all_targets; done 

    linuxsubdirs: dummy

          set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i; done 

    clean: 

          @set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i clean; done 

    dep:  

          @set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i fastdep; done 

    .PHONY: test

    test:

          @set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i test; done 

    run:  

    # @set -e; for i in $(SUBDIRS); do $(MAKE) -i -C $$i run; read junk; done

          make -C main run 

   src目录下的Rules.make文件给出了编译的一些规则,如下:

    #

    # This file contains rules which are shared between multiple Makefiles.

    # 

    #

    # False targets.

    #

    .PHONY: dummy 

    #

    # Special variables which should not be exported

    #

    unexport EXTRA_ASFLAGS

    unexport EXTRA_CFLAGS

    ifneq "$(ARCH)" "h8300"

    unexport EXTRA_LDFLAGS

    endif

    unexport EXTRA_ARFLAGS

    unexport SUBDIRS

    unexport SUB_DIRS

    unexport ALL_SUB_DIRS

    unexport MOD_SUB_DIRS

    unexport O_TARGET

    unexport O_OBJS

    unexport L_OBJS

    unexport M_OBJS

    unexport MI_OBJS

    unexport ALL_MOBJS

    # objects that export symbol tables

    unexport OX_OBJS

    unexport LX_OBJS

    unexport MX_OBJS

    unexport MIX_OBJS

    unexport SYMTAB_OBJS 

    unexport MOD_LIST_NAME 

    include ../dir.config

    include $(SRC_DIR)/arch.config 

    #

    # Get things started.

    #

    first_rule: sub_dirs

          $(MAKE) all_targets 

    #

    # Common rules

    #

    INC_DIR = -I$(SRC_DIR)/cal -I$(SRC_DIR)/xml -I$(SRC_DIR)/serial -I$(SRC_DIR)/packet -I$(SRC_DIR)/fifo -I$(SRC_DIR)/ping -I$(SRC_DIR)/interface -I$(SRC_DIR)/public 

    %.o: %.c

          @echo "Compiling..."

          @echo "$<"

          $(CXX) $(INC_DIR) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< 

    %.o: %.cpp

          @echo "Compiling..."

          @echo "$<" 

          $(CXX) $(INC_DIR) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< 

    # Rule to compile a set of .o files into one .o file

    # 

    ifeq (.depend,$(wildcard .depend))

    include .depend

    else

    .depend: fastdep 

    endif 

    ifneq ($(O_TARGET),$(O_OBJS))

    $(O_TARGET): .depend $(O_OBJS)

          @echo "Linking..."

          @echo $(O_OBJS) " --> " $@

          @$(LD) $(EXTRA_LDFLAGS) -r -o $@ $(O_OBJS)

    else

    $(O_TARGET): .depend

    endif

    #

    #

    # 

    all: $(O_OBJS)

          echo all 

    all_targets:  $(O_OBJS) $(O_TARGET) 

    # 

    #

    # Rule to compile a set of .o files into one .a file

    #

    ifdef L_TARGET

    $(L_TARGET): $(LX_OBJS) $(L_OBJS)

          rm -f $@

          $(AR) $(EXTRA_ARFLAGS) rcs $@ $(LX_OBJS) $(L_OBJS)

    endif 

    #

    # This make dependencies quickly

    #

    fastdep: dummy

          @echo "make fastdep"

          if [ -n "$(wildcard *.[chS])" ]; then \

          $(SCRIPTS_DIR)/mkdep *.[chS] > .depend; fi

          if [ -n "$(wildcard *.cpp)" ]; then \

          $(SCRIPTS_DIR)/mkdep *.cpp >> .depend; fi 

    #

    # A rule to make subdirectories

    #

    sub_dirs: dummy

    ifdef SUB_DIRS

          set -e; for i in $(SUB_DIRS); do $(MAKE) -C $$i; done

    endif

    #

    # A rule to do nothing

    #

    dummy: 

    config:

          cd $(ROOT_DIR); make config 

    c clean:

          rm -f *.o

          rm -f *.gdb

          rm -f .depend

          rm -f test

          rm -f core

          rm -f *.elf

          rm -f *.elf2flt  

    #

    # This is useful for testing

    #

    script:

          $(SCRIPT) 

    run: test

          @echo ... running ...

          @echo `pwd`/test

          @./test 

    #

    # This sets version suffixes on exported symbols

    # Uses SYMTAB_OBJS

    # Separate the object into "normal" objects and "exporting" objects

    # Exporting objects are: all objects that define symbol tables

    # 
 

    $(MX_OBJS):

          $(CC) $(CFLAGS) -DEXPORT_SYMTAB -c $(@:.o=.c) 

    $(LX_OBJS) $(OX_OBJS):

          $(CC) $(CFLAGS) -DMODVERSIONS -DEXPORT_SYMTAB -c $(@:.o=.c) 

    $(M_OBJS):

    ifdef MAKING_MODULES

    $(O_OBJS) $(L_OBJS):

    endif 
 

   在config 目录下,编写两个和架构有关的文件,对于x86平台,是arch.i386,如下:

    .EXPORT_ALL_VARIABLES:

    ###################################################################

    #

    # Vendor specific settings

    # 

    CONSOLE_BAUD_RATE = 19200 

    ###################################################################

    #

    # The makefiles need to know how to do things in different contexts

    # To save some pain we put it all here

    #

    # First settings we always want for all build

    # 

    # ARCH = kernel,  TARGET_ARCH = uClibc 

    MACHINE       = i386

    ARCH          = i386

    CROSS_COMPILE =

    CROSS         = $(CROSS_COMPILE) 

    # We've used -m5307 here because the bulk of the 5272 instruction timings

    # happen to be closer to the 5307 than the 5200 series.  Luckily, the

    # actual instructions on the two processors are essentially identical.

    # This should be fixed at some stage.

    CPUFLAGS  =

    CC        = $(CROSS_COMPILE)gcc

    AS        = $(CROSS_COMPILE)as

    CXX       = $(CROSS_COMPILE)g++

    AR        = $(CROSS_COMPILE)ar

    LD        = $(CROSS_COMPILE)ld

    OBJCOPY   = $(CROSS_COMPILE)objcopy

    RANLIB    = $(CROSS_COMPILE)ranlib 

    STRIPTOOL = $(CROSS_COMPILE)strip

    STRIP     = $(STRIPTOOL) 

    UCLINUX_BUILD_SET = 0     # have we set a special config below 

    ###################################################################

    #

    # General purpose lib building rules,  uClibc.config uses these when

    # possible

    # 
 

    ###################################################################

    # Settings for building user apps

    #

          CFLAGS  = -Wall -Wstrict-prototypes -O2 -g

          #CFLAGS  =  -Wstrict-prototypes -g

          LDFLAGS  = -m elf_i386

    ###################################################################

    # fall through,  do other config options perhaps

    #

    ifeq ($(UCLINUX_BUILD_SET),1)

    endif

    ################################################################### 

   在config 目录下,对于嵌入式平台,是arch.m68k,如下: 

    .EXPORT_ALL_VARIABLES:

    ###################################################################

    #

    # Vendor specific settings

    #

    CONSOLE_BAUD_RATE = 19200

    ###################################################################

    #

    # The makefiles need to know how to do things in different contexts

    # To save some pain we put it all here

    #

    # First settings we always want for all build

    #

    # ARCH = kernel,  TARGET_ARCH = uClibc 

    MACHINE       = m68k

    ARCH          = m68knommu

    CROSS_COMPILE = m68k-elf-

    CROSS         = $(CROSS_COMPILE) 

    # We've used -m5307 here because the bulk of the 5272 instruction timings

    # happen to be closer to the 5307 than the 5200 series.  Luckily, the

    # actual instructions on the two processors are essentially identical.

    # This should be fixed at some stage.

    CPUFLAGS  = -m5200

    CC        = $(CROSS_COMPILE)gcc

    AS        = $(CROSS_COMPILE)as

    CXX       = $(CROSS_COMPILE)g++

    AR        = $(CROSS_COMPILE)ar

    LD        = $(CROSS_COMPILE)ld

    OBJCOPY   = $(CROSS_COMPILE)objcopy

    RANLIB    = $(CROSS_COMPILE)ranlib

    ELF2FLT   = elf2flt

    STRIPTOOL = $(CROSS_COMPILE)strip

    STRIP     = $(STRIPTOOL) 

    UCLINUX_BUILD_SET = 0     # have we set a special config below 
 

    ###################################################################

    #

    # Settings for building user apps

    #

    #CFLAGS  = -m5200 -msep-data -g

    CFLAGS  = -m5200 -msep-data

    LDFLAGS = -Wl,-elf2flt

    SYSLIBS = -lc -lstdc++ -lgcc

    ###################################################################

    #

    # fall through,  do other config options perhaps

    # 

    ifeq ($(UCLINUX_BUILD_SET),1)

    endif

    ################################################################### 

   在config 目录下的config.in文件如下: 

    mainmenu_name 'uClinux Configuration'

    mainmenu_option next_comment

    comment 'Target Platform Selection'

    comment 'Choose a Vendor/Product combination.'

    choice 'Vendor/Product [Intel/i386 | Motorola/M5307C3] ' "1 CONFIG_DEFAULTS_INTEL_I386 \

    2 CONFIG_DEFAULTS_MOTOROLA_M5307C3 \

    " Intel/i386

    endmenu

4 结语

   本文讨论了uClinux平台上程序设计必须关注的一些特点,并对在uClinux进行高效程序开发做了一些讨论。

   由于uClinux是开源的,在uClinux上的开发努力永远不会停止。世界范围的技术专家在使用uClinux来构造商业化的产品,他们的工作的重要部分反过来对开源的社区作出了贡献。每当我们访问uClinux的网站,看到又出现了更新的源码发布或者更好的工具时,就会感觉到这个开发团体的热情和能力,并鞭策自己努力工作,争取为这个自由软件的发展作出自己的创造性贡献。 

责任编辑: sky_walker
发表评论 查看评论 加入收藏 Email给朋友 打印本文
如果你想对该文章评分, 请先登陆, 如果你仍未注册,请点击注册链接注册成为本站会员.
平均得分 0, 共 0 人评分
1 2 3 4 5 6 7 8 9 10

  Copyright © 2002 - 2005 iTePub.Group All Rights Reserved