《第3章 Linux下C编程基础.ppt》由会员分享,可在线阅读,更多相关《第3章 Linux下C编程基础.ppt(55页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第三章、第三章、Linux下下C编程编程gcc编译器编译器gdb调试器调试器make工程管理器工程管理器autotools 实验实验 gcc编译器编译器 GNU CC(简称为(简称为gcc)是)是GNU项目中符合项目中符合ANSI C标准的编译系统,能够编译用标准的编译系统,能够编译用C、C+和和Object C等语言编写的程序。等语言编写的程序。gcc不仅不仅功能强大,而且可以编译如功能强大,而且可以编译如C、C+、Object C、Java、Fortran、Pascal、Modula-3和和Ada等多种语言,而且等多种语言,而且gcc又是又是一个交叉平台编译器,它能够在当前一个交叉平台编译
2、器,它能够在当前CPU平平台上为多种不同体系结构的硬件平台开发软台上为多种不同体系结构的硬件平台开发软件,因此尤其适合在嵌入式领域的开发编译。件,因此尤其适合在嵌入式领域的开发编译。gcc编译过程编译过程#includeint main()printf(Hello!This is our embedded world!n);return 0;printf()的申明在头文件的申明在头文件stdio.h中中int printf(const char*fmt,.);printf()的实现在库的实现在库/lib/libc.so.6中中printf.o;gcc所支持后缀名解释所支持后缀名解释 gcc-预
3、处理阶段(预处理阶段(1)对包含的头文件(对包含的头文件(#include)和宏定义()和宏定义(#define、#ifdef等)进行处理等)进行处理。可以使用。可以使用gcc的选项的选项“-E”让让gcc在预处理结在预处理结束后停止编译过程。束后停止编译过程。rootlocalhost#gcc E hello.c o hello.i/*hello.i*/typedef int(*_gconv_trans_fct)(struct _gconv_step*,struct _gconv_step_data*,void*,_const unsigned char*,_const unsigned c
4、har*,_const unsigned char*,unsigned char*,size_t*);#2 hello.c 2int main()printf(Hello!This is our embedded world!n);return 0;gcc-编译阶段(编译阶段(2)gcc首先检查代码的规范性、是否有语法错首先检查代码的规范性、是否有语法错误等,以确定代码实际要做的工作,在检查误等,以确定代码实际要做的工作,在检查无误后,无误后,gcc把代码翻译成汇编语言。把代码翻译成汇编语言。用户可以使用用户可以使用“-S”选项来进行查看,该选选项来进行查看,该选项只进行编译而不进行汇编,生成
5、汇编代码。项只进行编译而不进行汇编,生成汇编代码。rootlocalhost#gcc S hello.i o hello.sgcc-编译阶段(编译阶段(2)/*hello.s*/.filehello.c .section.rodata .align 4.LC0:.string Hello!This is our embedded world!.text.globl main .type main,functionmain:pushl%ebp movl%esp,%ebp subl$8,%esp andl$-16,%esp movl$0,%eax addl$15,%eax addl$15,%eax
6、 shrl$4,%eax sall$4,%eax subl%eax,%esp subl$12,%esp pushl$.LC0 call puts addl$16,%esp movl$0,%eax leave ret .sizemain,.-main .ident GCC:(GNU)4.0.0 200X0Y19(Red Hat 4.0.0-8).section.note.GNU-stack,progbitsgcc-汇编阶段(汇编阶段(3)将编译阶段生成的将编译阶段生成的”.s”文件转成目标文件,文件转成目标文件,用选项用选项“-c”只产生目标代码,不链接。只产生目标代码,不链接。rootloca
7、lhost#gcc c hello.s o hello.ogcc-链接阶段(链接阶段(4)将库链接进来生成可执行文件将库链接进来生成可执行文件rootlocalhost#gcc hello.o o hellogcc-常用选项常用选项rootlocalhost gcc gcc hello1.c I /root/workplace/gcc/-o hello1如在如在/root/workplace/gcc下有两个文件下有两个文件/*hello1.c*/#includeint main()printf(“Hello!n”);return 0;/*my.h*/#includestdio.hgcc-库选项
8、库选项 将一些常用公共函数编译并集成到函数库中,不仅能够节省将一些常用公共函数编译并集成到函数库中,不仅能够节省内存资源,而且大大降低开发难度和开销,提高开发效率并内存资源,而且大大降低开发难度和开销,提高开发效率并增强程序的结构性。增强程序的结构性。静态库静态库是一系列的目标文件(是一系列的目标文件(.o文件)的归档文件(文件名文件)的归档文件(文件名格式为格式为libname.a),如果在编译某个程序时链接静态库,则),如果在编译某个程序时链接静态库,则链接器将会搜索静态库,从中提取出它所需要的目标文件并链接器将会搜索静态库,从中提取出它所需要的目标文件并直接拷贝到该程序的可执行二进制文件
9、直接拷贝到该程序的可执行二进制文件(ELF格式文件格式文件)之中;之中;动态库动态库(文件名格式为(文件名格式为libname.so.主版本号主版本号.次版本号次版本号.发行发行号号)在程序编译时并不会被链接到目标代码中,而是在程序)在程序编译时并不会被链接到目标代码中,而是在程序运行时才被载入。运行时才被载入。gcc-库选项库选项 Linux函数库的创建与使用函数库的创建与使用/*unsgn_pow.c:库程序:库程序*/unsigned long long unsgn_pow(unsigned int x,unsigned int y)unsigned long long res=1;if
10、(y=0)res=1;else if(y=1)res=x;else res=x*unsgn_pow(x,y-1);return res;/*pow_test.c*/#include#include int main(int argc,char*argv)unsigned int x,y;unsigned long long res;if(argc 3)|(sscanf(argv1,%u,&x)!=1)|(sscanf(argv2,%u,&y)!=1)printf(Usage:pow base exponentn);exit(1);res=unsgn_pow(x,y);printf(%u%u=%
11、un,x,y,res);exit(0);静态库的创建和使用静态库的创建和使用$gcc -c unsgn_pow.c$ar rcsv libpow.a unsgn_pow.o$gcc -o pow_test pow_test.c -L.lpow$./pow_test 2 102 10=1024 编译时链接到库编译时链接到库文件文件libpow.a中中动态库的创建和使用动态库的创建和使用$gcc -fPIC -Wall -c unsgn_pow.c$gcc -shared -o libpow.so unsgn_pow.o$gcc -o pow_test pow_test.c -L.lpow 在运行
12、可执行程序之前,需要注册动态库的路径在运行可执行程序之前,需要注册动态库的路径名。其方法有几种名。其方法有几种:修改:修改/etc/ld.so.conf文件,或者文件,或者修改修改LD_LIBRARY_PATH环境变量,或者将库文环境变量,或者将库文件直接拷贝到件直接拷贝到/lib或者或者/usr/lib目录下(这两个目录目录下(这两个目录为系统的默认的库路径名)。为系统的默认的库路径名)。$cp libpow.so/lib$./pow_test 2 102 10=1024 静态库与动态库的比较静态库与动态库的比较动态库只有在使用它的程序执行时才被链接动态库只有在使用它的程序执行时才被链接使用
13、,而不是将需要的部分直接编译入可执使用,而不是将需要的部分直接编译入可执行文件中,并且一个动态库可以被多个程序行文件中,并且一个动态库可以被多个程序使用故可称为共享库;使用故可称为共享库;静态库将会整合到程序中,因此在程序执行静态库将会整合到程序中,因此在程序执行时不用加载静态库。时不用加载静态库。从而可知,链接到静态库会使你的程序臃从而可知,链接到静态库会使你的程序臃肿,并且难以升级,但是可能会比较容易部肿,并且难以升级,但是可能会比较容易部署。而链接到动态库会使你的程序轻便,并署。而链接到动态库会使你的程序轻便,并且易于升级,但是会难以部署。且易于升级,但是会难以部署。gcc-警告选项(警
14、告选项(1)#includevoid main()long long tmp=1;printf(“This is a bad code!n”);return 0;gcc-警告选项(警告选项(2)$gcc ansi warning.c o warningwarning.c:在函数在函数“main”中:中:warning.c:7 警告:在无返回值的函数中,警告:在无返回值的函数中,“return”带返回值带返回值warning.c:4 警告:警告:“main”的返回类型不是的返回类型不是“int”#includevoid main()long long tmp=1;printf(“This is
15、a bad code!n”);return 0;gcc-警告选项(警告选项(3)$gcc pedantic warning.c o warningwarning.c:在函数在函数“main”中:中:warning.c:5 警告:警告:ISO C90不支持不支持“long long”warning.c:7 警告:在无返回值的函数中,警告:在无返回值的函数中,“return”带返回值带返回值warning.c:4 警告:警告:“main”的返回类型不是的返回类型不是“int”#includevoid main()long long tmp=1;printf(“This is a bad code!
16、n”);return 0;gcc-警告选项(警告选项(3)$gcc Wall warning.c o warningwarning.c:在函数在函数“main”中:中:warning.c:7 警告:在无返回值的函数中,警告:在无返回值的函数中,“return”带返回值带返回值warning.c:4 警告:警告:“main”的返回类型不是的返回类型不是“int”warning.c:5 警告:未使用的变量警告:未使用的变量“tmp”#includevoid main()long long tmp=1;printf(“This is a bad code!n”);return 0;gcc-优化选项优
17、化选项gcc可以对代码进行优化,通过编译选项可以对代码进行优化,通过编译选项“-On”来控制优化代码的生成,其中来控制优化代码的生成,其中n是一个是一个代表优化级别的整数。代表优化级别的整数。-O:告诉告诉GCC同时减小代码的长度和执行时同时减小代码的长度和执行时间,其效果等价于间,其效果等价于-O1。-O2:告诉告诉GCC除了完成所有除了完成所有“-O1”级别的级别的优化之外,同时还要进行一些额外的调整工优化之外,同时还要进行一些额外的调整工作,如处理器指令调度等。作,如处理器指令调度等。-O3:除除O2外,还包括循环展开和其他一外,还包括循环展开和其他一些与处理器特性相关的优化工作。些与处
18、理器特性相关的优化工作。gcc-体系结构相关选项体系结构相关选项编译器编译器gcc小结小结 gcc编译选项:编译选项:gcc options file-listfile-list 需要编译链接的文件名列表。需要编译链接的文件名列表。-E 仅完成预处理。仅完成预处理。-S 生成汇编代码文件。生成汇编代码文件。-c不进行链接不进行链接,只生成目标文件。只生成目标文件。-o file 输出文件名输出文件名,缺省名为缺省名为a.out。-On 编译优化级别,编译优化级别,n为为0、1、2、3,默认值为默认值为1,最,最通常的优化为通常的优化为2。-g在目标文件中嵌入调试信息,这些信息可以供如在目标文件
19、中嵌入调试信息,这些信息可以供如gdb之类的调试软件使用。之类的调试软件使用。最简编译最简编译gcc g hello.c -o hello gcc c hello.s o hello.ogcc S hello.i o hello.sgcc hello.c -o hello 生成后缀为生成后缀为elf的可执行文件的可执行文件 gcc E hello.c o hello.igcc O2 hello.c -o hello 编译器编译器gcc 小结小结 ELF可执行文件由下列部分组成可执行文件由下列部分组成ELF头头包含程序执行起始地址包含程序执行起始地址多个程序段多个程序段代码段、数据段、堆栈段代码
20、段、数据段、堆栈段每段的段头每段的段头描述了该段在程序地址空间的位置描述了该段在程序地址空间的位置符号表符号表用于调试用于调试n代码段代码段数据段数据段栈段栈段0第三章、第三章、Linux下下C编程编程gcc编译器编译器gdb调试器调试器make工程管理器工程管理器autotools 实验实验 gdb调试器调试器gdb调试器是一款调试器是一款GNU开发组织发布的开发组织发布的UNIX/Linux下的程序调试工具。虽然没有图形化下的程序调试工具。虽然没有图形化的友好界面,但是它强大的功能也足以与微软的的友好界面,但是它强大的功能也足以与微软的VC工具等媲美。工具等媲美。$gcc-g test.c
21、-o test$gdb testGNU gdb Red Hat Linux(6.3.0.0-1.21rh)Copyright 2004 Free Software Foundation,Inc.GDB is free software,covered by the GNU General Public License,and you arewelcome to change it and/or distribute copies of it under certain conditions.Type show copying to see the conditions.There is abs
22、olutely no warranty for GDB.Type show warranty for details.This GDB was configured as i386-redhat-linux-gnu.Using host libthread_db library/lib/libthread_db.so.1.(gdb)gdb调试器调试器(gdb)b 6Breakpoint 1 at 0 x804846d:file test.c,line 6.(gdb)l1#include 2 int sum(int m);3 int main()4 5 int i,n=0;6 sum(50);7
23、 for(i=1;i=50;i+)8 9 n+=i;10 (gdb)l11 printf(The sum of 150 is%d n,n);12 13 14 int sum(int m)15 16 int i,n=0;17 for(i=1;i=m;i+)18 19n+=i;20 21 printf(The sum of 1m is=%dn,n);20 (gdb)b 19(gdb)cBreakpoin 2,sum(m=50)at test.c:1919 printf(“The sum of 1-m is%dn”,n);(gdb)bt#0 sum(m=50)at test.c:19#1 0 x08
24、0483e8 in main()at test.c:6(gdb)info bNum Type Disp Enb Address What1 breakpoint keep y 0 x0804846d in main at test.c:6(gdb)rStarting program:/root/workplace/gdb/testReading symbols from shared object read from target memory.done.Loaded system supplied DSO at 0 x5fb000Breakpoint 1,main()at test.c:66
25、 sum(50);gdb调试器调试器(gdb)p n$1=0(gdb)p i$2=134518440(gdb)nThe sum of 1-m is 12757 for(i=1;i=50;i+)(gdb)ssum(m=50)at test.c:1616 int i,n=0;(gdb)cContinuing.The sum of 1-50 is:1275Program exited with code 031.(gdb)helpList of classes of commands:aliases-Aliases of other commandsbreakpoints-Making progra
26、m stop at certain pointsdata-Examining datafiles-Specifying and examining filesinternals-Maintenance commandsType help followed by a class name for a list of commands in that class.Type help followed by command name for full documentation.Command name abbreviations are allowed if unambiguous.(gdb)he
27、lp callCall a function in the program.The argument is the function name and arguments,in the notation of thecurrent working language.The result is printed and saved in the valuehistory,if it is not void.gdb工作环境相关命令工作环境相关命令 gdb设置断点与恢复命令设置断点与恢复命令 gdb中源码查看相关相关命令中源码查看相关相关命令 将路径添加到源文件搜索的路径的开头DIRgdb中查看运行数
28、据的相关命令中查看运行数据的相关命令 第三章、第三章、Linux下下C编程编程gcc编译器编译器gdb调试器调试器make工程管理器工程管理器autotools 实验实验 make工程管理器工程管理器make工程管理器用于管理较多的文件,其工程管理器用于管理较多的文件,其是一个是一个“自动编译管理器自动编译管理器”。这里的。这里的“自动自动”是指它能够:是指它能够:根据文件时间戳自动发现更新过的文件而减少编根据文件时间戳自动发现更新过的文件而减少编译的工作量;译的工作量;通过读入通过读入makefile文件的内容来执行大量的编译文件的内容来执行大量的编译工作工作 工程管理器工程管理器make例
29、一个工程项目由多个源文件组成,直接用例一个工程项目由多个源文件组成,直接用gcc将会很将会很麻烦麻烦Make会根据文件时间戳自动发现更新过的文件而减少会根据文件时间戳自动发现更新过的文件而减少编译工作量编译工作量make通过读入通过读入makefile文件查找文件依赖关系执行编文件查找文件依赖关系执行编译译 main.cheald1.hheald2.htest1.ctest2.cheald3.hmain.otest1.otest2.otest项目项目testmakefilemakefile基本结构(基本结构(1 1)makefile是是make读入的惟一配置文件,因此读入的惟一配置文件,因此本
30、节的内容实际就是讲述本节的内容实际就是讲述makefile的编写规的编写规则。在一个则。在一个makefile中通常包含如下内容:中通常包含如下内容:目标体(目标体(target):通常是目标文件或可):通常是目标文件或可执行文件;执行文件;依赖的文件:依赖的文件:创建目标体所依赖的文件;创建目标体所依赖的文件;命令:命令:创建目标体时需要运行的创建目标体时需要运行的命令命令,这,这一行必须以制表符(一行必须以制表符(tab键)开头。键)开头。makefile格式格式makefile例子例子使用使用make项目管理器项目管理器 makefilemakefile基本结构(基本结构(2 2)tar
31、get:dependency_filescommand/*该行必须以该行必须以tab键开头键开头*/hello.o:hello.c hello.h gcc c hello.c o hello.o$make 或或 make hello.o gcc c hello.c o hello.o$lshello.c hello.h hello.o makefile makefilemakefile变量变量变量用来代替一个文本字符串变量用来代替一个文本字符串 变量定义的两种方式变量定义的两种方式递归展开方式递归展开方式VAR=var简单方式简单方式 VAR:=var变量使用变量使用$(VAR)OBJS=ka
32、ng.o yul.oCC=gccCFLAGS=-Wall-O-gdavid:$(OBJS)$(CC)$(OBJS)-o davidkang.o:kang.c kang.h$(CC)$(CFLAGS)-c kang.c-o kang.oyul.o:yul.c yul.h$(CC)$(CFLAGS)-c yul.c-o yul.omakefilemakefile变量变量变量种类变量种类用户自定义变量用户自定义变量预定义变量预定义变量自动变量自动变量环境变量环境变量 OBJS=kang.o yul.oCC=gccCFLAGS=-Wall-O-gdavid:$(OBJS)$(CC)$-o$kang.o
33、:kang.c kang.h$(CC)$(CFLAGS)-c$-o$yul.o:yul.c yul.h$(CC)$(CFLAGS)-c$-o$用户自定义变量用户自定义变量MakefileMakefile变量变量-预定义变量预定义变量OBJS=kang.o yul.oCC=gccCFLAGS=-Wall-O-gdavid:$(OBJS)$(CC)$-o$kang.o:kang.c kang.h$(CC)$(CFLAGS)-c$-o$yul.o:yul.c yul.h$(CC)$(CFLAGS)-c$-o$预定义变量预定义变量Makefile变量变量-自动变量自动变量$*$+$?$%OBJS=ka
34、ng.o yul.oCC=gccCFLAGS=-Wall-O-gdavid:$(OBJS)$(CC)$-o$kang.o:kang.c kang.h$(CC)$(CFLAGS)-c$-o$yul.o:yul.c yul.h$(CC)$(CFLAGS)-c$-o$MakefileMakefile变量变量-环境变量环境变量make在启动时会自动读取系统当前已在启动时会自动读取系统当前已经定义了的经定义了的环境变量环境变量,并且会创建与之,并且会创建与之具有相同名称和数值的变量,但是具有相同名称和数值的变量,但是 如如果用户在果用户在makefile中定义了相同名称的中定义了相同名称的变量,那么用户
35、自定义变量将会覆盖同变量,那么用户自定义变量将会覆盖同名的环境变量名的环境变量 makefile规则 makefile的规则是的规则是make进行处理的进行处理的依据,它包括了目标体、依赖文件依据,它包括了目标体、依赖文件及其之间的命令语句。及其之间的命令语句。隐含规则隐含规则模式规则模式规则隐式规则隐式规则隐含规则能够告诉隐含规则能够告诉make怎样使用传统的怎样使用传统的规则完成任务,这样,当用户使用它们规则完成任务,这样,当用户使用它们时就不必详细指定编译的具体细节,而时就不必详细指定编译的具体细节,而只需把目标文件列出即可只需把目标文件列出即可 例子例子OBJS=kang.o yul.
36、oCC=gccCFLAGS=-Wall-O-gdavid:$(OBJS)$(CC)$-o$OBJS=kang.o yul.oCC=gccCFLAGS=-Wall-O-gdavid:$(OBJS)$(CC)$-o$kang.o:kang.c kang.h$(CC)$(CFLAGS)-c$-o$yul.o:yul.c yul.h$(CC)$(CFLAGS)-c$-o$模式规则模式规则为多个文件建立相同的规则,以简化为多个文件建立相同的规则,以简化makefile的编写的编写格式类似于普通规则,这个规则中的相格式类似于普通规则,这个规则中的相关文件前必须用关文件前必须用“%”标明标明例例OBJS=k
37、ang.o yul.oCC=gccCFLAGS=-Wall-O-gdavid:$(OBJS)$(CC)$-o$%.o:%.c$(CC)$(CFLAGS)-c$-o$make的命令行选项的命令行选项 工程管理器工程管理器makemakefile例子例子OBJ=main.o test1.o test2.o CC=gcctest:$(OBJ)$(CC)o test$(OBJ)main.o:main.c head1.h head2.h$(CC)c main.c -o main.otest1.o:test1.c head2.h$(CC)c test1.c -o test1.otest2.o:test2.
38、c head3.h$(CC)c test2.c -o test2.o install:cp test /home/tmpclean:rm -f *.omain.cheald1.hheald2.htest1.ctest2.cheald3.htestmain.otest1.otest2.o/伪目标,无依赖文件,伪目标,无依赖文件,make认为是最新不执行认为是最新不执行/伪目标,同上伪目标,同上伪目标的编译伪目标的编译:#make install#make clean-c$-o$-c$-o$-c$-o$第三章、第三章、Linux下下C编程编程gcc编译器编译器gdb调试器调试器make工程管理器工
39、程管理器autotools 实验实验 autotools对于一个较大的项目而言编写makefile难度较大autotools系列工具只需用户输入简单的目标文件、依赖文件、文件目录等就可以轻松地生成makefileautotools工具还可以完成系统配置信息的收集,从而可以方便地处理各种移植性的问题Linux上的软件开发一般都用autotools来制作makefileautotools流程图流程图./configureautomakeconfigure.scanconfigure.inaclocal.m4makefilemakefile.inconfig.h.inconfigureautosca
40、naclocalautoheadermakefile.am第三章、第三章、Linux下下C编程编程gcc编译器编译器gdb调试器调试器make工程管理器工程管理器autotools 实验实验 实验实验 1 vi使用练习使用练习1实验目的实验目的通过指定指令的通过指定指令的vi操作练习,使读者能够熟操作练习,使读者能够熟练使用练使用vi中的常见操作,并且熟悉中的常见操作,并且熟悉vi的的3种模种模式,如果读者能够熟练掌握实验内容中所要式,如果读者能够熟练掌握实验内容中所要求的内容,则表明对求的内容,则表明对vi的操作已经很熟练了。的操作已经很熟练了。2实验内容实验内容 详见教材详见教材实验实验
41、2 用用gdb调试程序的调试程序的bug 1实验目的实验目的 通过调试一个有问题的程序,使读者进一步通过调试一个有问题的程序,使读者进一步熟练使用熟练使用vi操作,而且熟练掌握操作,而且熟练掌握gcc编译命编译命令及令及gdb的调试命令,通过对有问题程序的的调试命令,通过对有问题程序的跟踪调试,进一步提高发现问题和解决问题跟踪调试,进一步提高发现问题和解决问题的能力。这是一个很小的程序,只有的能力。这是一个很小的程序,只有35行,行,希望读者认真调试。希望读者认真调试。2实验内容实验内容详见教材详见教材实验实验 3 编写包含多文件的编写包含多文件的makefile1实验目的实验目的 通过对包含多文件的通过对包含多文件的makefile的编写,熟悉的编写,熟悉各种形式的各种形式的makefile,并且进一步加深对,并且进一步加深对makefile中用户自定义变量、自动变量及预中用户自定义变量、自动变量及预定义变量的理解。定义变量的理解。2实验过程实验过程详见教材详见教材本章基本要求本章基本要求u 熟悉熟悉gcc编译器的基本原理编译器的基本原理 u 熟练使用熟练使用gcc编译器的常用选项编译器的常用选项 u 熟练使用熟练使用gdb调试技术调试技术 u 熟悉熟悉makefile基本原理及语法规范基本原理及语法规范