《Linux操作系统教程》-第15章 LinuxC编程基础_第1页
《Linux操作系统教程》-第15章 LinuxC编程基础_第2页
《Linux操作系统教程》-第15章 LinuxC编程基础_第3页
《Linux操作系统教程》-第15章 LinuxC编程基础_第4页
《Linux操作系统教程》-第15章 LinuxC编程基础_第5页
已阅读5页,还剩34页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

15.1Linux编程基础C语言是Linux编程语言事实上的标准,Linux操作系统中包括Linux内核绝大部分是用C语言编写的。Linux中最常用的程序编辑器有vi(vim)和emacs;编译器为GCC;调试器为GDB。C语言的编程离不开头文件与库函数,在Linux中函数库和头文件的保存位置如下所示。1.函数库/lib系统必备共享库。/usr/lib标准共享库和静态库。/usr/i486-linux-libc5/liblibc5兼容性函数库。/usr/X11R6/libX11R6的函数库。/usr/local/lib本地函数库。下一页返回15.1Linux编程基础2.头文件/usr/include用户空间头文件。/usr/local/include本地头文件。/usr/src/include内核态头文件。上一页返回15.2GCC编译器15.2.1GCC简介在为Linux开发应用程序时,绝大多数情况下使用的都是C语言,因此几乎每一位Linux程序员面临的首要问题都是如何编译C语言源程序代码。目前Linux下最常用的C语言编译器是GCC(GNUCompilerCollection),它是GNU项目中符合ANSIC标准的编译系统,能够编译用C、C++和ObjectC等语言编写的程序。GCC不仅功能十分强大,结构也异常灵活。GCC是可以在多种硬体平台上编译出可执行程序的编译器,其执行效率与一般的编译器相比,平均效率要高20%~30%。GCC支持编译的一些源文件的后缀如下。下一页返回15.2GCC编译器在使用GCC编译程序时,编译过程可以细分为如下4个阶段:(1)预处理(Pre-Processing);(2)编译(Compiling);(3)汇编(Assembling);(4)链接(Linking)。Linux程序员可以根据自己的需要让GCC在编译的任何阶段结束,检查或使用编译器在该阶段的输出信息,或者对最后生成的二进制文件进行控制,以便通过加入不同数量和种类的调试代码来为今后的调试做好准备。与其他常用的编译器一样,GCC也提供了灵活而强大的代码优化功能,利用它可以生成执行效率更高的代码。上一页下一页返回15.2GCC编译器GCC提供了30多条警告信息和3个警告级别,使用它们有助于增强程序的稳定性和可移植性。此外,GCC还对标准的C和C++语言进行了大量的扩展,提高了程序的执行效率,有助于编译器进行代码优化,能够减轻编程的工作量。上一页返回下一页15.2GCC编译器15.2.2GCC命令格式1.基本格式gcc[options][filenames]2.编译选项说明GCC编译器有100多个编译选项,以下是最常用的选项。(1)-E:只进行预处理,结果输出到标准输出,除非用-o指定输出文件(一般指定文件后缀为.i)。(2)-S:进行预处理、编译,产生汇编代码。输出的文件后缀默认为.s。(3)-c:进行预处理、编译、汇编,产生目标代码。输出的文件后缀默认为.o。下一页返回上一页15.2GCC编译器(4)-o:指定输出的文件名。(5)-g:产生符号调试工具(GNU的GDB)所需要的符号信息,要想对源代码进行调试,必须加入这个选项。(6)-Idirname:指定额外的头文件搜索路径dirname目录。由于在Linux中,头文件默认放在/usr/include中,当用户希望使用其他位置的头文件时,可以用这个选项告诉GCC到指定的dirname目录中去寻找需要的头文件。(7)-Ldirname:指定额外的函数库搜索路径dirname目录。在预设状态下,链接程序ld在系统的预设路径中(如/usr/lib)寻找所需要的档案库文件,这个选项告诉链接程序,首先到-L指定的目录中去寻找,然后到系统预设路径中寻找。上一页下一页返回15.2GCC编译器(8)-lname:在链接时,装载名字为libname.a的函数库,该函数库位于系统预设的目录或者由-L选项确定的目录下。例如,-lm表示链接名为libm.a的数学函数库。15.2.3GCC的库函数处理在Linux下使用C语言开发应用程序时,几乎都要使用第三方函数库,通常来讲都需要借助一个或多个函数库的支持才能够完成相应的功能。从程序员的角度看,函数库实际上就是一些头文件(.h)和库文件的集合。虽然Linux下大多数函数都默认将头文件放到/usr/include/目录下,而库文件则放到/usr/lib/目录下,但并不是所有的情况都是这样。正因如此,GCC在编译时必须让编译器知道如何来查找所需要的头文件和库文件。上一页下一页返回15.2GCC编译器Linux下的库文件分为两大类,分别是动态链接库(通常以.so结尾)和静态链接库(通常以.a结尾),两者的差别仅在于,程序执行时所需的代码是在运行时动态加载的,还是在编译时静态加载的。默认情况下,GCC在链接时优先使用动态链接库,只有当动态链接库不存在时才考虑使用静态链接库。如果需要的话可以在编译时加上-static选项,强制使用静态链接库。例如,如果在/home/david/lib/目录下有链接时所需要的库文件libfoo.so和libfoo.a,为了让GCC在链接时只用到静态链接库,可以使用下面的命令:gccfoo.c-L/home/david/lib-static"ldavid-odavid上一页下一页返回15.2GCC编译器15.2.4GCC编译过程下面将以一个实例来说明如何使用GCC编译器。通过实例能够帮助大家迅速理解GCC的工作原理,并将其立即运用到实际的项目开发中去。例题1:hello.c。#include<stdio.h>intmain(intargc,char*argv){printf("HelloLinux/n");}要编译这个程序,只要在命令行下执行如下命令:$gcchello.c-ohello上一页下一页返回15.2GCC编译器$./helloHelloLinux这样,GCC编译器会生成一个名为hello的可执行文件,然后执行./hello就可以看到程序的输出结果了。为了更好地理解GCC的工作过程,可以把上述编译过程分成几个步骤单独进行,并观察每步的运行结果。第一步要进行预编译,使用-E参数可以让GCC在预处理结束后停止编译过程:$gcc-Ehello.c-ohello.i此时若查看hello.i文件中的内容,会发现stdio.h的内容确实都插到文件里去了,而且对预处理的宏定义也都作了相应的处理。上一页下一页返回15.2GCC编译器下一步是将hello.i编译为目标代码,这可以通过使用-c参数来完成:$gcc-chello.i-ohello.oGCC默认将.i文件看成是预处理后的C语言源代码,因此上述命令将自动跳过预处理步骤而开始执行编译过程,也可以使用-x参数让GCC从指定的步骤开始编译。最后一步是将生成的目标文件链接成可执行文件:$gcchello.o-ohello在采用模块化的设计思想进行软件开发时,通常整个程序是由多个源文件组成的,相应地就形成了多个编译单元,使用GCC能够很好地管理这些编译单元。假设有一个由david.c和xueer.c两个源文件组成的程序,为了对它们进行编译,并最终生成可执行程序davidxueer,可以使用下面这条命令:上一页下一页返回15.2GCC编译器$gccdavid.cxueer.c-odavidxueer如果同时处理的文件不止一个,GCC仍然会按照预处理、编译和链接的过程依次进行。如果深究起来,上面这条命令大致相当于依次执行如下3条命令:gccdavid.c-odavid.ogccxueer.c-oxueer.ogccdavid.oxueer.o-odavidxueer上一页下一页返回15.2GCC编译器在编译一个包含许多源文件的工程时,若只用一条gcc命令来完成编译是非常浪费时间的。假设项目中有100个源文件需要编译,并且每个源文件中都包含10000行代码,如果像上面那样仅用一条GCC命令来完成编译工作,那么GCC需要将每个源文件都重新编译一遍,然后再全部链接起来。很显然,这样浪费的时间相当多,尤其是当用户只是修改了其中某一个文件的时候,完全没有必要将每个文件都重新编译一遍,因为很多已经生成的目标文件是不会改变的。要解决这个问题,关键是要灵活运用GCC,同时还要使用make工具。上一页返回15.3GNUmake15.3.1GNUmake简介GNU提供了一个很好的实现项目管理的工具make。make是一个解释makefile文件中指令的命令工具。一般来说,大多数的IDE都有这个命令,比如Delphi的make,VisualC++的nmake,Linux下GNU的make。人们通常利用make工具来自动完成编译工作,这些工作包括:如果仅修改了某几个源文件,则只重新编译这几个源文件;如果某个头文件被修改了,则重新编译所有包含该头文件的源文件。在大型的研发项目中,通常有几十到上百个源文件,如果每次均手工输入GCC命令进行编译,会非常不方便。利用make这种自动编译命令可大大简化研发工作,避免不必要的重新编译。下一页返回15.3GNUmake15.3.2makefile文件make命令执行时,需要一个makefile文件,以告诉make命令需要怎样去编译和连接程序。makefile文件需要按照某种语法进行编写,其说明了如何编译各个源文件并连接生成可执行文件,且定义了源文件之间的依赖关系。当修改了其中的某个源文件时,则该文件和依赖于它的所有源文件都要重新进行编译。一旦makefile文件编写好,则每次更改了源文件后,只要执行make就足够了,所有必要的重新编译将会自动执行。make程序利用makefile中的数据库和文件的最后修改时间来确定哪个文件需要更新;对于需要更新的文件,make执行数据库中记录的命令,可以提供命令行参数给make来控制哪些文件需要重新编译。上一页下一页返回15.3GNUmakemakefile文件的操作规则如下:·如果这个工程没有编译过,所有C文件都要编译并被连接;·如果这个工程的某几个C文件被修改,只需编译被修改的C文件,并连接目标程序;·如果这个工程的头文件被改变了,需要编译引用了这几个头文件的C文件,并连接目标程序。只要makefile文件写得足够好,所有的这一切,只用一个make命令就可以完成,make命令会自动根据当前文件的修改情况来确定哪些文件需要重新编译,从而自动编译所需要的文件并连接目标程序。makefile的语法规则如下。target:dependencyfiles上一页下一页返回15.3GNUmakecommand上述语法包括3个基本内容。target:需要make工具创建的目标体,通常是目标文件和可执行文件。dependencyfiles:目标体target依赖于哪些文件。command:创建每个目标体时需要运行的命令,需要注意的是,每个command前必须用Tab键产生缩进,否则运行makefile时会出错。上一页下一页返回15.3GNUmake15.3.3make运用实例本项目使用4个源文件;main.c用来调用其他3个程序;program1.c计算s=1+2+3+…+10;program2.c用来计算s=1*2*3…*10;program3.c打印“*************”。步骤1:编辑源程序。使用vi编辑器编辑源程序。main.c的源程序如下:#include"stdio.h"voidsum();voidmul();上一页下一页返回15.3GNUmakevoidprintstar();intmain(){printstar();sum();mul();printstar();}program1.C源程序:上一页下一页返回15.3GNUmake#include"stdio.h"voidsum(){inti,s;s=0;for(i=0;i<=10;i++){s=s+i;}printf("%10d\n",s);}上一页下一页返回15.3GNUmakeprogram2.c源程序:#include"stdio.h"voidmul(){inti;//s在此没有声明,设置错误s=1;for(i=1;i<=5;i++){s=s*i;

上一页下一页返回15.3GNUmake}printf("%10d\n",s);}program3.c源程序:#include"stdio.h"voidprintstar(){printf("***************\n");}上一页下一页返回15.3GNUmake步骤2:编辑生成makefile文件。步骤3:使用make编译。从显示信息可以看出编译没有通过,而且在prgram2.o处理上出现问题,使用vi编辑器编辑makefile文件,将prgram2.o修改成program2.o,重新使用make编译。上一页下一页返回15.3GNUmake如果在没有修改的情况下再执行makeprogram命令,会有提示信息显示当前的项目已经是最新的项目,没有必要重新编译,这样也可以节省用户的时间与精力,由make根据makefile文件自动判断是否需要进行重新编译。步骤4:执行make编译之后得到的可执行文件program,如图15-18所示。步骤5:修改源程序program3.c、program1.c。步骤6:使用makeprogram命令重新编译与上次编译的过程相对比,发现编译的方法与顺序是不一样的,原因就是program2.c、main.c不需要重新编译。步骤7:执行重新编译生成的可执行文件。上一页返回15.4调试器GDB15.4.1GDB基础程序员经常面对的一个问题就是调试。当程序编译完成后,可能无法正常运行;或许程序会彻底崩溃;或许只是不能正常地运行某些功能;或许它的输出会被挂起;或许不会提示要求正常的输入。无论在何种情况下,跟踪这些问题,特别是在大的工程中,将是开发中最困难的部分,程序调试器往往是解决这一问题最重要的工具。GDB调试器是GNU组织发布的、UNIX/Linux下的一个强大的程序调试工具。虽然它没有友好的图形化界面,但在UNIX/Linux下它强大的功能足以与VisualC++、BCB等图形化调试器媲美。下一页返回15.4调试器GDBGDB主要用于调试可执行文件,这个文件必须提供调试版本,包含调试信息。另外,GDB还可以用于查看由于程序异常退出而生成的core文件。有了调试版本的可执行文件,用户就可以在命令行载入可执行文件进行调试了。如果不提供参数运行或者需要调试另外一个程序,可以使用file命令加载另外一个文件。GDB为程序的调试提供了众多的命令,这些命令涵盖了从简单文件载入、设置断点到查看程序堆栈等各个方面。一般来说,GDB具备如下4个方面的功能。(1)启动程序时,可以按照用户自定义的要求运行程序。(2)可以让被调试的程序在用户所指定的断点处暂停。(3)当程序被暂停时,可以检查此时用户程序中所发生的变化。上一页下一页返回15.4调试器GDB(4)动态改变用户程序的执行环境。启动GDB的方法有如下3种。(1)gdbprogram:调试一个用户的调试版可执行文件,一般在当前目录下。(2)gdbprogramcore:同时调试一个调试版运行程序和core文件。(3)gdbprogramPID:如果用户程序是一个服务程序,则用户可指定该服务程序运行时的进程ID,GDB会自动调用attach上去并调试它。上一页下一页返回15.4调试器GDB15.4.2GDB调试程序过程(1)初始化。(2)暂停程序。①设置断点。②设置运行参数和环境变量。③观察断点。④跟踪调试命令。⑤输入和输出重定向。⑥设置异常捕捉点。⑦捕捉信号。上一页下一页返回15.4调试器GDB⑧改变程序运行。(3)查看信息。①查看数据。②查看内存。③查看栈信息。15.4.3GDB应用实例编制一程序,输出10!,计算1+2+13+…+100,其结果输出到屏幕上。步骤1:使用vi编辑器编制程序,程序的名字为prog1,程序如下。#include<stdio.h>上一页下一页

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论