欢迎来到三一文库! | 帮助中心 三一文库31doc.com 一个上传文档投稿赚钱的网站
三一文库
全部分类
  • 研究报告>
  • 工作总结>
  • 合同范本>
  • 心得体会>
  • 工作报告>
  • 党团相关>
  • 幼儿/小学教育>
  • 高等教育>
  • 经济/贸易/财会>
  • 建筑/环境>
  • 金融/证券>
  • 医学/心理学>
  • ImageVerifierCode 换一换
    首页 三一文库 > 资源分类 > PPT文档下载  

    第4章嵌入式Linux程序设计基础.ppt

    • 资源ID:2120846       资源大小:539.51KB        全文页数:70页
    • 资源格式: PPT        下载积分:8
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录 QQ登录   微博登录  
    二维码
    微信扫一扫登录
    下载资源需要8
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    第4章嵌入式Linux程序设计基础.ppt

    第4章 嵌入式Linux程序设计基础,本章要点,1、嵌入式Linux编译器GCC 2、“文件包含”处理 3、make命令和Makefile文件 4、使用 autotools系列工具 5、位运算,单击此处编辑母版副标题样式,4.1 嵌入式Linux编译器,Linux下C语言编译过程 GCC编译器,Linux下C语言编译过程,Linux下的C语言程序设计与在其他环境中的C程序设计一样,主要涉及编辑器、编译链接器、调试器及项目管理工具。 (1)编辑器. Linux下的编辑器就如Windows下的记事本、写字板等一样,完成对所录入文字的编辑功能。Linux中最常用的编辑器有vi(vim)和emacs,,(2)编译链接器。 编译是指源代码转化生成可执行代码的过程,它所完成的主要工作如图所示。编译过程是非常复杂的,它包括词法、语法和语义的分析、中间代码的生成和优化、符号表的管理和出错处理等。在Linux中,最常用的编译器是gcc编译器。 (3)调试器 调试器并不是代码执行的必备工具,而是专为方便程序员调试程序而用的。gdb是绝大多数Linux开发人员所使用的调试器,它可以方便地设置断点、单步跟踪等。 (4)项目管理器。 Linux中的项目管理器“make”有些类似于Windows中Visual c+里的“工程”,它是一种控制编译或者重复编译软件的工具,另外,它还能自动管理软件编译的内容、方式和时机,使程序员能够把精力集中在代码的编写上而不是在源代码的组织上。,GCC编译器,Linux系统下的gcc(GNU C Compiler)是GNU推出的功能强大、性能优越的多平台编译器,是GNU的代表作之一。gcc可以在多种硬体平台上编译出可执行程序,其执行效率与一般的编译器相比平均效率要高20%30%。 GCC编译器能将C、C+语言源程序、汇编程序编译、链接成可执行文件。在Linux系统中,可执行文件没有统一的后缀,系统从文件的属性来区分可执行文件和不可执行文件。,GCC编译器,使用GCC编译程序时,编译过程可以被细分为四个阶段: 预处理(Pre-Processing) 编译(Compiling) 汇编(Assembling) 链接(Linking),GCC编译器,gcc通过后缀来区别输入文件的类别: .c为后缀的文件: C语言源代码文件 .a为后缀的文件: 是由目标文件构成的库文件 .C,.cc或.cxx 为后缀的文件: 是C+源代码文件 .h为后缀的文件: 头文件 .i 为后缀的文件: 是已经预处理过的C源代码文件 .ii为后缀的文件: 是已经预处理过的C+源代码文件 .o为后缀的文件: 是编译后的目标文件 .s为后缀的文件: 是汇编语言源代码文件 .S为后缀的文件: 是经过预编译的汇编语言源代码文件。,起步(演示),hello.c: #include int main(void) printf (Hello world!n); return 0; 编译和运行这段程序: # gcc hello.c -o hello # ./hello 输出:Hello world!,Gcc的基本用法和选项,Gcc最基本的用法 gcc options filenames -c:只编译,不连接成为可执行文件。 -o output_filename:确定输出文件的名称为output_filename,同时这个名称不能和源文件同名。 -g:产生符号调试工具(GNU的gdb)所必要的符号资讯,要想对源代码进行调试,我们就必须加入这个选项。 -O:对程序进行优化编译、链接,采用这个选项,整个源代码会在编译、链接过程中进行优化处理,产生的可执行文件的执行效率较高。 -O2,比-O更好的优化编译、连接,当然整个编译、连接过程会更慢。,编译选项(optimize.c),#include int main(void) double counter; double result; double temp; for (counter = 0; counter 2000.0 * 2000.0 * 2000.0 / 20.0 + 2020; counter += (5 - 1) / 4) temp = counter / 1979; result = counter; printf(Result is %lfn, result); return 0; ,1. gcc optimize.c -o optimize time ./optimize 2. gcc O optimize.c -o optimize time ./optimize 对比两次执行的输出结果不难看出,程序的性能的确得到了很大幅度的改善,-static:静态链接库文件 例:gcc static hello.c -o hello 库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀。例如:libhello.so libhello.a。当使用静态库时,连接器找出程序所需的函数,然后将它们拷贝到可执行文件,一旦连接成功,静态程序库也就不再需要了。然而,对动态库而言,就不是这样,动态库会在执行程序内留下一个标记指明当程序执行时,首先必须载入这个库。由于动态库节省空间,linux下进行连接的缺省操作是首先连接动态库。 演示:静态链接与动态链接可执行文件大小比较,-Wall:生成所有警告信息 -w:不生成任何警告信息,4.2 “文件包含”处理,1、头文件 在C语言中,需要利用头文件来定义结构、常量以及声明函数的原型。大多数C的头文件都存放在 /usr/include及其子目录下。 引用以上目录中的头文件在编译的时候无需加上路径,但如果程序中引用了其他路径的头文件,需要在编译的时候用 I 参数。,4.2 “文件包含”处理,-Idirname: 将dirname所指出的目录加入到程序头文件目录列表中。 C程序中的头文件包含两种情况 #include #include “B.h” 对于,预处理程序cpp在系统预设的头文件目录(如/usr/include)中搜寻相应的文件;而对于”,cpp在当前目录中搜寻头文件。这个选项的作用是告诉cpp,如果在当前目录中没有找到需要的文件,就到指定的dirname目录中去寻找。 例:gcc foo.c -I /home/include -o foo,-lname:在连接时,装载名字为“libname.a”的函数库,该函数库位于系统预设的目录或者由-L选项确定的目录下。例如,-lm表示连接名为“libm.a”的数学函数库。 例:gcc foo.c -L /home/lib -lfoo -o foo,2、“文件包含”处理 “文件包含”处理,意思是把另外一个源文件的内容包含到本程序中来。其作用是减少编写程序的重复劳动,即把一些要重复使用的东西,编写到一个“头文件”(*.h)中,然后在程序中用 include命令来实现“文件包含”的操作。,例如: n=1+2+3+100 求和运算。 1 #include 2 int main() 3 int x=100,s=0,i=1; 5 while(i=x) 6 s=s+i; 7 i+; 8 9 printf(“ sum= %dn“,s); 10 return 0; 11 ,为了让加法部分能重复使用,将加法部分写成一个函数int sum(int n)。 int mysum(int n) int i=1,ss=0; while(i=n) ss=ss+i; i+; return (ss); ,再在主函数中调用它 1 #include 2 int mysum(int n); 3 int main() 4 5 int x=100; 6 int s=0; 7 s=mysum(x); 8 printf(“ sum= %dn“,s); 9 return 0; 10 ,注意:上述程序中的第2行语句 int mysum(int n); 是必不可少的。由于mysum(int n)函数的定义是从第11行语句开始,而调用mysum(int n)函数的语句在第7行。因此,要在调用之前声明这个函数。 下面进一步将程序中具有独立功能的mysum()函数分割出来。该程序可分割为下列3个程序:mysum.h、mysum.c和ex_sum.c。,(1)程序mysum.h: 1 /* mysum.h */ 2 int mysum(int n); (2)程序mysum.c: 1. /* mysum.c */ 2. int mysum(int n) 3. 4. int i=1,ss=0; 5. while(i=n) 6. ss=ss+i; 7. i+; 8. 9. return (ss); 10. ,主程序ex_sum.c: 1. /* ex_sum.c */ 2. #include 3. #include “mysum.h“ 4. int main() 5. 6. int x=100; 7. int s=0; 8. s=mysum(x); 9. printf(“sum=%dn“,s); 10. return 0; 11. ,在Linux环境下,执行编译程序命令: gcc ex_sum.c mysum.c -o sum 此命令将ex_sum.c和 mysum.c编译成一个在Linux环境下的可执行文件sum。 在Linux环境下运行可执行文件sum, ./sum 结果如下: sum=5050,4.3 Make命令和Makefile工程管理,Linux程序员必须学会使用GNU make来构建和管理自己的软件工程。GNU 的make能够使整个软件工程的编译、链接只需要一个命令就可以完成。 make在执行时, 需要一个命名为Makefile的文件。Makefile文件描述了整个工程的编译,连接等规则。其中包括:工程中的哪些源文件需要编译以及如何编译;需要创建那些库文件以及如何创建这些库文件、如何最后产生我们想要得可执行文件。,Makefile 是 一个配置文件。 Makefile 中通常包含如下内容:用于说明如何生成一个或多个目标文件规则 需要由make 工具创建的目标体, 通常是目标文件或可执行文件; 要创建的目标体所依赖的文件; 创建每个目标体时需要运行的命令。,Makefile的格式为: targets : prerequisites command 目标依赖命令 main.o : main.c gcc c main.c 目标?依赖?命令? *命令需要以【TAB】键开始*,认识Make,编写一个Makefile文件如下: sum: ex_sum.o mysum.o gcc ex_sum.o mysum.o -o sum ex_sum.o:ex_sum.c gcc -c ex_sum.c mysum.o: mysum.c mysum.h gcc -c mysum.c,注意, “gcc ex_sum.c mysum.c -o sum”前面不是空格,而是按下“tab”键的符号位。 我们将其保存为:makefile,文件名没有后缀。然后,在Linux环境下执行make,其运行结果如下: # make gcc -c ex_sum.c gcc -c mysum.c gcc ex_sum.o mysum.o -o sum 将ex_sum.c和 mysum.c编译成在Linux环境下的可执行文件sum。,在Makefile 中,规则的顺序是很重要的,因为,Makefile中只应该有一个最终目标,其它的目标都是被这个目标所连带出来的,所以一定要让make知道你的最终目标是什么。一般来说,定义在Makefile中的目标可能会有很多,但是第一条规则中的目标将被确立为最终的目标。,伪目标,Makefile中把那些没有任何依赖只有执行动作的目标称为“伪目标”(phony targets)。 .PHONY : clean clean : rm f hello main.o func1.o func2.o “.PHONY” 将“clean”目标声明为伪目标,文件名,make命令默认在当前目录下寻找名字为makefile或者Makefile的工程文件,当名字不为这两者之一时,可以使用如下方法指定: make f 文件名,示例,该程序有mytool1.h、mytool2.h、mytool1.c、mytool2.c 等文件需要编译。编写Makefile文件: main: main.o mytool1.o mytool2.o gcc -o main main.o mytool1.o mytool2.o main.o: main.c gcc -c main.c mytool1.o: mytool1.c mytool1.h gcc -c mytool1.c mytool2.o: mytool2.c mytool2.h gcc -c mytool2.c,再次运行make,这时,make 会自动检查相关文件的时间戳。 首先,在检查“main”、“main.o”、“ mytool1.o”和“mytool2.o”这3 个文件的时间戳之前,它会向下查找那些把“main.o”、“ mytool1.o”或“mytool2.o”作为目标文件的时间戳。如果这些文件中任何一个的时间戳比它们新,则用gcc命令将此文件重新编译。这样,make 就完成了自动检查时间戳的工作,开始执行编译工作。这也就是 Make 工作的基本流程。,Makefile 变量,hello: main.o func1.o func2.o gcc main.o func1.o func2.o -o hello 思考1:如果要为hello目标添加一个依赖,如:func3.o,该如何修改? 答案1: hello: main.o func1.o func2.o func3.o gcc main.o func1.o func2.o func3.o -o hello 答案2: obj=main.o func1.o func2.o func3.o hello: $(obj) gcc $(obj) -o hello,Makefile 变量,为了进一步简化编辑和维护 Makefile,make 允许在 Makefile 中创建和使用变量。变量是在 Makefile 中定义的名字,用来代替一个文本字符串,该文本字符串称为该变量的值。 在Makefile 中的变量定义有两种方式:一种是递归展开方式,另一种是简单方式。 递归展开方式的定义格式为:VAR=var。 简单扩展方式的定义格式为:VAR:=var。 Make 中的变量无论采用哪种方式定义使用时格式均为:$(VAR)。,例如,OBJS = main.o mytool1.o mytool2.o CC = gcc main: $(OBJS) $(CC) $(OBJS) -o main main.o: main.c $(CC) -c main.c mytool1.o: mytool1.c mytool1.h $(CC) -c mytool1.c mytool2.o: mytool2.c mytool2.h $(CC) -c mytool2.c,在makefile中,存在系统默认的自动化变量 $:代表所有的依赖文件 $:代表目标 $:代表第一个依赖文件 例: hello: main.o func1.o func2.o gcc main.o func1.o func2.o -o hello = hello: main.o func1.o func2.o gcc $ -o $,进一步简化,OBJS = main.o mytool1.o mytool2.o CC = gcc main: $(OBJS) $(CC) $ -o $ main.o: main.c $(CC) -c $ -o $ mytool1.o: mytool1.c mytool1.h $(CC) -c $ -o $ mytool2.o: mytool2.c mytool2.h $(CC) -c $ -o $,Makefile中“#”字符后的内容被视作注释。 hello: hello.c gcc hello.c o hello :取消回显,隐式规则(Implicit Rule),在我们使用Makefile时,有一些语句经常使用,而且使用频率非常高的东西,隐式规则能够告诉 make使用默认的方式来完成编译任务,这样,当用户使用它们时就不必详细指定编译的具体细节,而只需把目标文件列出即可。Make 会自动按隐式规则来确定如何生成目标文件。 OBJS = main.o mytool1.o mytool2.o CC = gcc main: $(OBJS) $(CC) $ -o $,模式规则(Pattern Rule),模式规则规定,在目标文件的定义时需要用“%”字符。“%”的意思是表示一个或多个任意字符,与文件名匹配。 例如:“%.c”表示以“.c”结尾的文件名(文件名的长度至少为3),而“s.%.c”则表示以“s.”开头,“.c”结尾的文件名(文件名的长度至少为5个字符)。 OBJS = main.o mytool1.o mytool2.o CC = gcc main: $(OBJS) $(CC) $ -o $ %.o: %.c $(CC) -c $ -o $,如果一个目标在Makefile中的所有规则都没有命令列表,make会尝试在内建的隐含规则(Implicit Rule)数据库中查找适用的规则。make的隐含规则数据库可以用make -p命令打印,打印出来的格式也是Makefile的格式,包括很多变量和规则。,# default OUTPUT_OPTION = -o $ # default CC = cc # default COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c %.o: %.c # commands to execute (built-in): $(COMPILE.c) $(OUTPUT_OPTION) $,#号在Makefile中表示单行注释,就像C语言的/注释一样。CC是一个Makefile变量,用CC = cc定义和赋值,用$(CC)取它的值,其值应该是cc。Makefile变量像C的宏定义一样,代表一串字符,在取值的地方展开。cc是一个符号链接,通常指向gcc,在有些UNIX系统上可能指向另外一种C编译器。 CFLAGS这个变量没有定义,$(CFLAGS)展开是空,CPPFLAGS和TARGET_ARCH也是如此。这样$(COMPILE.c)展开应该是cc空空空-c,去掉所有的“空”得到cc-c,注意中间留下4个空格,所以%.o: %.c规则的命令$(COMPILE.c)$(OUTPUT_OPTION)$展开之后是cc-c-o$,和上面的编译命令已经很接近了。,%.o: %.c是一种特殊的规则,称为模式规则(Pattern Rule)。现在回顾一下整个过程,在我们的Makefile中以hello.o为目标的规则都没有命令列表,所以make会查找隐含规则,发现隐含规则中有这样一条模式规则适用,hello.o符合%.o的模式,现在%就代表hello(称为hello.o这个名字的Stem),再替换到%.c中就是hello.c。,GDB程序调试,GDB是GNU发布的一款功能强大的程序调试工具。GDB主要完成下面三个方面的功能: 1、启动被调试程序。 2、让被调试的程序在指定的位置停住。 3、当程序被停住时,可以检查程序状态(如变量值)。,起步(tst.c),#include void main() int i; long result = 0; for(i=1; i=100; i+) result += i; printf(“result = %d n“, result ); ,GDB快速进阶,1.编译生成可执行文件: gcc -g tst.c -o tst 2.启动GDB gdb tst 3. 在main函数处设置断点 break main 4. 运行程序 run 5. 单步运行 next 6. 继续运行 continue,启动GDB,1. gdb 调试程序名 例:gdb helloworld 2. gdb file 调试程序名,GDB命令,list(l) 查看程序 break(b) 函数名 在某函数入口处添加断点 break(b) 行号 在指定行添加断点 break(b) 文件名:行号 在指定文件的指定行添加断点 break(b) 行号if 条件 当条件为真时,指定行号处断点生效,例b 5 if i=10,当i等于10时第5行断点生效,GDB命令,info break 查看所有设置的断点 delete 断点编号 删除断点 run(r) 开始运行程序 next(n) 单步运行程序(不进入子函数) step(s) 单步运行程序(进入子函数) continue(c) 继续运行程序 print(p) 变量名 查看指定变量值 finish 运行程序,直到当前函数结束 watch 变量名 对指定变量进行监控 quit(q) 退出gdb,4.5 位运算,4.5.1 位运算符,C语言提供了六种位运算符: &(按位与)、|(按位或)、(按位异或)、(取反)、(右移)。,1、按位与运算,位运算符 按位与运算:只有对应的两个二进位均为1时,结果位才为1 ,否则为0。参与运算的数以补码方式出现。 例如:9 & 5可写成算式如下: 可见 9 & 5 = 1。,按位与运算通常用来对某些位清0或保留某些位。 例如把a 的高八位清0,保留低八位,可作 a ,2、 按位或运算,只要对应的二个二进位有一个为1时,结果位就为1。 例如:9|5可写算式如下: 可见9|5=13。,main() int a=9,b=5,c; c=a|b; printf(“a=%d/nb=%d/nc=%d/n“,a,b,c); ,3、按位异或运算,当两对应的二进位相异时,结果为1。 例如 95 : main() int a=9; a=a15; printf(“a=%d/n“,a); ,4、求反运算,其功能是对参与运算的数的各二进位按位求反。 例如,9的运算为:(0000000000001001)结果为:1111111111110110。,5、 左移运算,把“ ”左边的运算数的各二进位全部左移若干位,由“”右边的数指定移动的位数,高位丢弃,低位补0。,例如: a4,6、 右移运算,把“ ”左边的运算数的各二进位全部右移若干位,“”右边的数指定移动的位数。 例如:设 a=15,a2表示把000001111右移为00000011(十进制3)。,4.5.2 位表达式,将位运算符连接起来所构成的表达式称为位表达式。在这些位运算符中,其优先级依次为: (取反运算符)、(左移或右移)、&(按位与)或|(按位或)或(按位异或)。,a = 5; 就等价于: a = a 5; 再比如:GPDR 完成了对GPDR的清0。,一个常用的操作是用 ,也可以用|、 /* 将x的第6位设置为1 */,本章小结,本章是在嵌入式Linux中进行程序设计的基础,介绍了Gcc编译器的使用,虽然它的选项较多,但掌握常用的一些选项即可。介绍了Make工程管理器的使用,这里包括Makefile的基本结构、Makefile的变量定义及其规则和 make命令的使用。还介绍了autotools的使用,这在项目设计中是非常有用的工具。最后简单介绍了位运算。,感谢您的关注,

    注意事项

    本文(第4章嵌入式Linux程序设计基础.ppt)为本站会员(本田雅阁)主动上传,三一文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一文库(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    经营许可证编号:宁ICP备18001539号-1

    三一文库
    收起
    展开