1嵌入式Linux应用程序开发主讲人:方攀Email:fpmystar@gmail.comBlog:fpmystar.cublog.cn2Copyright2007ProchipElectronicsCo,ltd.AllRightsReserved.Nottobereproducedbyanymeanswithoutpriorwrittenconsent.嵌入式Linux应用程序开发嵌入式Linux应用程序开发及交叉编译:HelloWorld!嵌入式Linux内核模块开发:HelloModule!Linux环境下多进程及多线程编程3Copyright2007ProchipElectronicsCo,ltd.AllRightsReserved.Nottobereproducedbyanymeanswithoutpriorwrittenconsent.1.1Linux应用程序介绍在为Linux开发应用程序时,绝大多数情况下使用的都是C语言,因此几乎每一位Linux程序员面临的首要问题都是灵活运用C编译器.目前Linux下最常用的C语言编译器是GCC(GNUCompilerCollection),它是GNU项目中符合ANSIC标准的编译系统,能够编译用C、C++和ObjectC等语言编写的程序.GCC不仅功能非常强大,结构也异常灵活.最值得称道的一点就是它可以通过不同的前端模块来支持各种语言,如Java、Fortran、Pascal、Modula-3和Ada等.开放自由和灵活是Linux的魅力所在,而这一点在GCC上的体现就是程序员通过它能够更好地控制整个编译过程.在使用GCC编译程序时,编译过程可以被细分为四个阶段:◆预处理(Pre-Processing)◆编译(Compiling)◆汇编(Assembling)◆链接(Linking)Linux程序员可以根据自己的需要让GCC在编译的任何阶段结束,以便检查或使用编译器在该阶段的输出信息,或者对最后生成的二进制文件进行控制,以便通过加入不同数量和种类的调试代码来为今后的调试做好准备.和其它常用的编译器一样,GCC也提供了灵活而强大的代码优化功能,利用它可以生成执行效率更高的代码GCC提供了30多条警告信息和三个警告级别,使用它们有助于增强程序的稳定性和可移植性此外,GCC还对标准的C和C++语言进行了大量的扩展,提高程序的执行效率,有助于编译器进行代码优化,能够减轻编程的工作量.4Copyright2007ProchipElectronicsCo,ltd.AllRightsReserved.Nottobereproducedbyanymeanswithoutpriorwrittenconsent.1.1应用程序起步—编写源文件在/root/下建一个自己的目录#mkdirproject#cdproject#vimhelloworld.c#includestdio.hintmain(void){printf(Welovearm,welovesep4020!!\n);return1;}5Copyright2007ProchipElectronicsCo,ltd.AllRightsReserved.Nottobereproducedbyanymeanswithoutpriorwrittenconsent.代码注意问题◆main函数的返回值应该是int类型;◆main函数在终止前没有调用“return1;”语句来结尾。6Copyright2007ProchipElectronicsCo,ltd.AllRightsReserved.Nottobereproducedbyanymeanswithoutpriorwrittenconsent.1.2编译helloworld.c(1)在pc机上编译能在pc机上运行的应用程序的方法#gcc-ohelloworld_pchelloworld.c(这个是用i386的gcc编译器编译的,所以只能在pc机的linux环境中运行)(2)在pc机上编译能在sep4020板子上运行的应用程序的方法#arm-linux-gcc-ohelloworld_armhelloworld.c(这个是用arm的交叉gcc编译器编译的,所以可以下载到板子上运行)7Copyright2007ProchipElectronicsCo,ltd.AllRightsReserved.Nottobereproducedbyanymeanswithoutpriorwrittenconsent.1.3运行helloworld程序(1)在pc机上运行i386的程序[root@localhostcode]#./helloworld_pcWelovearm,welovesep4020!!(2)在开发板上运行应用程序将应用程序helloworld_arm拷贝到/nfs/demo文件夹下[root@localhostcode]#cphelloworld_arm/nfs/demo/#cddemo/demo#./helloworld_armWelovearm,welovesep4020!!8Copyright2007ProchipElectronicsCo,ltd.AllRightsReserved.Nottobereproducedbyanymeanswithoutpriorwrittenconsent.2.1编写HelloModule源代码前面我们介绍了一个简单的Linux程序HelloWorld,它是运行于用户态的应用程序,现在我们再介绍一个运行于内核态的HelloModule程序,它其实是一个最简单的驱动程序模块。我们将HelloModule的源代码放置于/root/project/module目录,名称为hellomodule.c,内容如下:9Copyright2007ProchipElectronicsCo,ltd.AllRightsReserved.Nottobereproducedbyanymeanswithoutpriorwrittenconsent.#includelinux/kernel.h#includelinux/module.hMODULE_LICENSE(GPL);staticint__initsep4020_hello_module_init(void){printk(Hello,sep4020moduleisinstalled!\n);return0;}staticvoid__exitsep4020_hello_module_cleanup(void){printk(Good-bye,sep4020modulewasremoved!\n);}module_init(sep4020_hello_module_init);module_exit(sep4020_hello_module_cleanup);10Copyright2007ProchipElectronicsCo,ltd.AllRightsReserved.Nottobereproducedbyanymeanswithoutpriorwrittenconsent.2.2编译HelloModule源代码由于这个模块是加到嵌入式linux的内核中的,所以它肯定会用到许多嵌入式linux源码的头文件的,我们的嵌入式linux的内核源码位置在/linux-3.2/下面,这中间的链接过程非常复杂,为了不让我们手动输入编译指令,一般编译2.6版本的驱动模块需要把驱动代码加入内核代码树,并做相应的配置,如下步骤Step1:把刚才的源码文件拷贝到/linux-3.2/drivers/char/sep4020_char目录下Step2:编辑配置/linux-3.2/drivers/char/sep4020_char的Kconfig文件,加入驱动选项(注意tristate前面有tab键)configSEP4020_HELLOMODULEtristatesep4020hellomoduledriver使之在makemenuconfig的时候出现;11Copyright2007ProchipElectronicsCo,ltd.AllRightsReserved.Nottobereproducedbyanymeanswithoutpriorwrittenconsent.12Copyright2007ProchipElectronicsCo,ltd.AllRightsReserved.Nottobereproducedbyanymeanswithoutpriorwrittenconsent.Step3:修改Makefile文件,在其中加入:obj-$(CONFIG_SEP4020_HELLOMODULE)+=hellomodule.oStep4:这时回到/linux-3.2源代码根目录位置,执行makemodules13Copyright2007ProchipElectronicsCo,ltd.AllRightsReserved.Nottobereproducedbyanymeanswithoutpriorwrittenconsent.2.3把HelloModule下载到开发板并安装使用14Copyright2007ProchipElectronicsCo,ltd.AllRightsReserved.Nottobereproducedbyanymeanswithoutpriorwrittenconsent.3Linux进程编程3.1Linux进程的概念3.2Linux下的进程启动3.3进程控制编程3.4守护进程编程3.5进程间通信15Copyright2007ProchipElectronicsCo,ltd.AllRightsReserved.Nottobereproducedbyanymeanswithoutpriorwrittenconsent.3.1Linux进程的概念(1)进程是一个独立的可调度的活动;(2)进程是一个抽象实体,当它执行某个任务时,将要分配和释放各种资源(P.Denning);(3)进程是可以并行执行的计算部分。以上进程的概念都不相同,但其本质是一样的。它指出了进程是一个程序的一次执行的过程。它和程序是有本质区别的,程序是静态的,它是一些保存在磁盘上的指令的有序集合,没有任何执行的概念;而进程是一个动态的概念,它是程序执行的过程,包括了动态创建、调度和消亡的整个过程。它是程序执行和资源管理的最小单位。16Copyright2007ProchipElectronicsCo,ltd.AllRightsReserved.Nottobereproducedbyanymeanswithoutpriorwrittenconsent.进程控制块(1)进程是Linux系统的基本调度单位,那么从系统的角度看如何描述并表示它的变化呢?进程标识符:当一个进程产生时,系统都会为它分配一个标识符;进程所占的内存区域:每个进程执行时都需要占用一定的内存区域,此区域用于保存该进程所运行的程序代码和使用的程序变量。每一个进程所占用的内存是相互独立的,因此改变一个进程所占内存中数据的任何改动,都只对该进程产生影响,不会影响到其它进程的顺利执行;文件描述符:当一个进程在执行时,它需要使用一些相关的文件描述符。文件描述符描述了被打开文件的信息,不同的进程打开同一个文件时,所使用的文件描述符是不同的。一个进程文件描述符的改变并不会对其它的进程打开同一个文件的描述符产生任何影响;17Copyright2007ProchipElectronicsCo,ltd.AllRightsReserved.Nottobereproducedbyanymeanswithoutpriorwrittenconsent.进程控制块(2)安全信息:一个进程的安全信息包括