chap6-系统编程_第1页
chap6-系统编程_第2页
chap6-系统编程_第3页
chap6-系统编程_第4页
chap6-系统编程_第5页
已阅读5页,还剩68页未读, 继续免费阅读

下载本文档

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

文档简介

1、第六章 UNIX系统编程基础1.程序设计环境2.基于系统支持的程序设计3.UNIX环境C编程4.常用函数库6.1 程序设计环境程序设计环境 学习程序设计从程序语言开始,但还应了解程序执行和程序与外界的交互问题。1.理想态的程序运行环境理想态的程序运行环境用户程序直接控制和使用各种设备,完成各种操作。针对一个简单程序:main() int c; while ( ( c=getchar() != EOF )putchar(c);认为执行过程为:在单用户单任务环境中基本符合。2. 多任务环境下程序执行多任务环境下程序执行多任务中每一时刻都会有多个用户程序提出访问请求,因此会有:如此混乱的情况,程序将

2、无法运行。为使多道环境中的程序正确执行,需要OS管理。用户程序需要系统核心区程序的管理,达到各自任务的执行。6.2 基于系统支持的程序设计基于系统支持的程序设计1. 建立系统编程的思想建立系统编程的思想 理解多道环境程序执行状况,转换用户程序是执行主体的认识。 了解OS可提供的服务及服务方式。 充分利用OS提供服务功能解决实际问题。 尽量使编写的程序最大限度的满足系统平台的支持能力。2. UNIX可提供的系统支持可提供的系统支持1)文件及目录管理 采用多层目录结构,系统中有唯一的根目录节点,每层目录中都可包含子目录和文件节点。 目录本身是一特殊文件,受文件系统管理。目录的文件类型为d。 文件名

3、和文件扩展名的命名规则,“.”和“.”文件的含义和作用。2)标准输入/输出文件 UNIX中的设备是特殊文件,输入/输出是在文件系统管理下完成的。 系统通过文件描述符实现对文件的访问。 标准I/O文件将随进程创建而创建,它们是标准输入0,标准输出1,标准错误2。 标准I/O文件可以被重定向操作改变。3)程序执行与进程生成 在UNIX中一个程序的运行必将伴随着一个或多个进程的产生。 进程有唯一标识PID,可用以下程序获取:#include “apue.h” int main(void)printf(“ This Process ID is %dn”, getpid( );exit(0);4)程序执

4、行时的出错处理 当函数或系统调用出错时返回一个负值,同时对全局变量errno进行设置,具体内容与所用系统调用有关 。对需要返回对象指针的函数,出错时将返回一个空指针null 。 用户程序可调用以下函数输出错误信息:#include char *strerror(int errnum);#include void perror(const char *msg);5)善于了解用户ID及用户组ID信息系统有基于用户信息的安全控制机制,它们可以有效地保护程序安全。可用以下程序提取用户或组ID信息:#include “apue.h”int main(void)printf( “user ID= %d,

5、group ID= %dn”,getuid( ), getgid( );exit (0);3. UNIX可提供多种系统调用可提供多种系统调用 输入/输出控制类 进程与线程管理类 存储管理类 设备控制类 时钟管理类 本地进程通信类 网络进程通信类4. 系统调用与库函数间关系使用上区别不大,内部实现机制完全不同。 系统调用是OS提供的服务,函数是高级语言级提供的服务。 库函数通常需要系统调用提供服务,反之不然。 系统调用只提供基本功能,而库函数可更加方便易用。6.3 在在UNIX环境中设计环境中设计C程序程序1. 需要掌握的工具需要掌握的工具 掌握一种编辑器 了解makfile文件的编写规则 掌握

6、C编译器的使用方法 掌握一些软件管理工具的使用方法 了解常用库函数的使用方式2. C程序的编译与调试程序的编译与调试int main(int argc,char *argv) printf(Hello Linux ); 假设有以下C程序,程序名为hello.c:在命令行输入以下命令完成编译:$gcc o hello hello.c输入以下命令执行该程序:$./hello编译:编译:编译程序读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码,再由汇编程序转换为机器语言,并且按照操作系统对可执行文件格式的要求链接生成可执行程序。程序执行必经之路程序执行必经之路-

7、编译编译C源程序头文件预编译处理(cpp)编译程序本身优化程序汇编程序链接程序可执行文件UNIX环境下C编译系统的工作过程在此阶段,预编译程序读取c源程序,对其中的伪指令(以#开头的指令)和特殊符号进行处理。C语言中的伪指令主要包括以下:(1)宏定义指令,如# define Name TokenString,#undef等。(2)条件编译指令,如#ifdef,#ifndef,#else,#elif,#endif,等等。(3)头文件包含指令,如#include “FileName”或者#include 等。(4)特殊符号,预编译程序可以识别一些特殊的符号。编译预处理编译预处理经过预编译得到的输出

8、文件中,将只有常量。如数字、字符串、变量的定义,以及C语言的关键字,如main,if,else,for,while,+,-,*,,等等。编译程序所要作得工作就是通过词法分析和语法分析,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码。编译阶段编译阶段经过优化的代码,通过汇编程序,翻译成目标机器指令。对于被翻译系统处理的每一个C语言源程序,都将会得到相应的目标文件。其中所存放的是与源程序等效的目标机器语言代码。目标文件由段组成。通常一目标文件中至少有两个段:代码段 该段中所包含的主要是程序的指令。该段一般是可读和可执行的,但一般却不可写。 数据段 主要存放程序中要用到的

9、各种全局变量或静态的数据。一般数据段都是可读,可写,可执行的。 汇编过程汇编过程(1)可重定位文件 其中包含有适合于其它目标文件链接来创建一个可执行的或者共享的目标文件的代码和数据。(2)共享的目标文件 这种文件存放了适合于在两种上下文里链接的代码和数据。第一种是链接程序可把它与其它可重定位文件及共享的目标文件一起处理来创建另一个目标文件;第二种是动态链接程序将它与另一个可执行文件及其它的共享目标文件结合到一起,创建一个进程映象。(3)可执行文件 它包含了一个可以被操作系统创建一个进程来执行之的文件。目标文件目标文件的的三种类型三种类型汇编程序生成的实际上是第一种类型的目标文件。对于后两种还需

10、要链接程序的工作处理方能得到。关于三种目标文件的说明关于三种目标文件的说明由汇编程序生成的目标文件并不能立即就被执行,其中可能还有许多没有解决的问题。需要经链接程序的处理。链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够诶操作系统装入执行的统一整体。根据开发人员指定的同库函数的链接方式的不同,链接处理可分为两种:(1)静态链接(2)动态链接经过上述过程,C源程序就最终被转换成可执行文件了。链接程序链接程序任务:完成对源程序的编译工作。cc命令在UNIX系统中,实现C源程序到可执行文件的这一转

11、换过程的工具是cc。在大多数系统中cc实际上是一个shell命令文件。有些系统中的C编译程序可能并不叫cc而是其它的一个什么名称,如Sun工作站上常用的gcc等等。大多数系统中C编译命令的用法基本上都是类似的。cc的基本用法的基本用法需要将C源程序的名字写在CC命令行中,cc即可对这些源文件(.c文件)进行编译。如果这些源文件中都没有main()函数的定义,那么cc将只能生成与各源文件相对应的目标文件(.o文件)。如果某个源文件中有关于main()函数的定义,则将把所有目标文件链接起来生成相应的可执行文件。缺省的情况下这个可执行文件的名字将是a.out。例子$ cc main.c output

12、.c link.c用ls命令看看目录内容a.out就是生成的可执行文件为了能够个性化名字需要 o 选项cc o myprog main.c output.c link.c可执行文件可执行文件cc命令行中的文件参数可以不全是.c文件,目标文件(.o)文件以后编译过程中所得到的其他文件,如预编译后文件(.i文件),编译后的汇编程序(.s文件)等都可作为文件参数。文件参数文件参数cc命令还提供了其他许多有用的命令行选项。借助于这些选项可以对编译过程进行进一步的控制。如:cc只完成某些阶段的编译工作,指定对头文件的搜索目录,指定对代码进行优化,指定在代码中加入一些供调试程序所用的信息,等等。cc命令命

13、令常用选项常用选项cc命令命令常用选项常用选项-仅进行编译预处理在命令行中加上-P选项可以使cc仅完成对.c文件的预处理工作,而后面的编译,汇编,优化,链接则都不作,例如:$ cc -P hello.c在cc命令行中加上-S 选项,可以使cc只调用预处理程序和编译程序以生成与源程序相应的汇编代码。与每一个C源文件相应的汇编程序被放到相应的.s文件中。例如:$ cc -S main.c output.c link.ccc命令命令常用选项常用选项-仅生成汇编代码在cc命令行中加上-C选项,只生成源文件的目标代码而不对这些代码进行链接,此时编译系将只生成与各源文件相对应的.o文件(目标文件)。如:$

14、 cc -c main.c output.c link.ccc命令命令常用选项常用选项-仅生成目标文件C源程序中用# include指令包含了某个头文件时,根据文件名指定方法的不同,C编译系统将在不同的目录下去寻找指定的头文件:在用尖括号()指定头文件名时,预处理程序将在系统中存放头文件的标准位置(通常是/usr/include目录)寻找指定的头文件。在用双引号(“”)指定投文件名时,预处理程序将先在包含此头文件的C源程序所在的目录中(一般为当前目录),去查找该头文件。找不到时再到标准目录下去查找。cc命令命令常用选项常用选项-头文件搜索路径针对那些头文件既不在标准位置,又不在与C源程序同一目

15、录时的情况,CC命令提供了I(Include)选项,以供用户自己指定头文件所在地目录。cc命令命令常用选项常用选项-头文件搜索路径例如,对于main.c、output.c、link.c中所包含的头文件common.h,我们假定其后来被放在目录$HOME/include目录下,而这些C文件则被放在$HOME/myprog目录下。此时在$HOME/myprog目录下对这两个C文件进行编译时,可使用如下命令:$ cc -I #HOME/include main.c、output.c、link.c此时对于这两个C文件中的#include common.h,预处理程序将先在$HOME/myprog目录下

16、,然后再$HOME/include目录下,最后再系统标准位置查找common.h。I选项也能改变那些用尖括号()指定的头文件的搜索顺序,此时预编译程序将首先在-I指定的目录下,然后才在标准位置搜索。I选项可以多次重复使用。这样我们将能够指定多个非标准的头文件目录。cc命令命令常用选项常用选项-头文件搜索路径优化只应对最终提交的可执行程序进行。在CC命令行中加上-O选项可以使编译系统对代码进行优化:$ cc -O -o main.c、output.c、link.c优化对于不同的程序效果可能是不同的。有些程序优化不优化都不会有什么区别。在有些系统上(如Sun OS),对程序的优化可以分成不同的级别

17、(一般是1至4级)cc命令命令常用选项常用选项-优化处理为了能够使用UNIX的符号调试程序(sdb)对程序进行调试,必须在目标代码中加入一些有关的程序变量和语句信息,以便sdb能够跟踪函数调用、显示变量的值以及设置断点,等等。在cc命令行中加入-g选项将能够实现上述要求,如:$ cc -g -o myprog main.c、output.c、link.c这样生成的myprog就可以用sdb进行调试了。cc命令命令常用选项常用选项-在目标文件中加入调试用的信息程序的调试有几种不同的级别。最高级别当然是编程人员通过自己肉眼观察和推断,找出那些有毛病的代码并修改之。最低级别是对汇编代码进行调试。由于

18、汇编语言代码的复杂、冗长与不直观。UNIX开发环境提供了汇编级的调试工具adb。使用得最多的是源程序级即符号级的调试,在此种调试方式下能够把高级语言的语句当作一个可执行的最小单位,在调试程序中使用源程序中出现的符号和代码的行号来交互式地引用变量或控制语句的执行。调试调试程序程序UNIX环境下进行符号级调试的工具有两个。一个是dbx,使用它可以确定程序崩溃的位置、显示变量和表达式的值,在程序中设置断点以及跟踪程序的执行,等等。这一调试工具主要来源于BSD 的UNIX系统中使用的比较多。另外一个符号级的调试工具是sdb。sdb的最初来源于UNIX System V。它的功能同dbx类似。 Linu

19、x 中的gdb也是调试工具 。调试程序调试程序调试程序的主要功能调试程序的主要功能包括:使程序员能监视程序中设置变量的值在程序执行中的变化情况。可设置断点以使程序在指定的代码行上停止执行,以观察执行效果。可设置程序单行的执行操作,以观察每一步的执行效果。 第一种情况(这是大多数用户都会碰到的),程序在运行过程中忽然跳了出来,屏幕上显示一个xxxxcore dumped消息,然后Shell提示符就又显示出来了。操作系统把进程当时的内存映象写到当前目录下的一个名叫core的文件中。使用sdb来检查此core文件,以决定出错的地点以及程序执行的状态,如函数间的调用关系、变量的值,等等。需要调试程序的

20、情况需要调试程序的情况第二种情况,程序可能并没有什么异常行为,但就是怎么也得不到正确的输出结果。这时需要在该进程运行过程中对之进行调试。使用sdb逐条语句地跟踪程序的执行过程,并在执行过程中检查有关变量的值的变化情况。上述两种情况并不是绝然分开的。实际上它们可以结合在一起使用。需要调试程序的情况需要调试程序的情况第三种情况,对活动过程(正在运行的进程)进行调试的情况。例如,假定某个程序正在后台运行,但注意到该程序的某些部分执行起来非常慢,这时可以在不杀死这个进程的情况下对之进行调试:$ sdb /proc/11111111为待调试进程的进程号,用户可以用PS命令得到。需要调试程序的情况需要调试

21、程序的情况$ sdb myprog即可进入sdb调试程序。sdb将接受三个参数:待调试的可执行文件名; 待调试的core文件名,一般缺省是core; 由冒号分隔的一个目录表,sdb将在这些目录表中去查找有关的源文件。此目录表的缺省设置是当前目录 开始调试开始调试sdb都将显示出*提示符。在此提示符之下可以输入各种sdb命令在sdb的使用中要注意三个“当前”概念:(1)当前文件 即当前将要被执行的语句所在的那个源程序文件(2)当前函数 即当前将要被执行的语句所在的那个函数(3)当前行 这个概念只有在编译时加入-g选项才会有,它指的是将要被执行的那条语句。sdb使用使用注意注意sdb 命令命令1.

22、源程序的显示w,该命令指示sdb显示源程序中的当前行为中心的前后10行的内容并保持当前行不变P 显示当前行 l 显示对应于当前指令的那条语句 Z 显示当前行开始的下面10条语句 Ctrl+D 显示当前行之后(不包括当前行)的第10条语句 n 显示第n条语句,这里n是一个数 改变当前行在用户显示语句时,当前行也会相应地发生变化。2、程序执行控制断点的设置和删除在sdb中设置断点的方法比较多。但基本是b命令的变种。如下语句在main()函数的第一个可执行行(非变量定义这类语句)设置一个断点:* main:b直接用行号来设置断点。* 10b在设置完断点之后要将其删除,可以使用d命令。如:* main

23、:dsdb将把在main()函数中设置的第一个可执行行上的断点删除。3、sdb中启动程序的运行在设置好所需的断点之后我们就可以重新启动程序的运行了。这可以使用r命令。如:r (可以带参数)想不带任何参数来重新启动程序的运行,可使用R4、控制程序的单步或者连续执行在用r(R)命令启动程序的运行之后,sdb将在第一个断点处暂停程序的运行。此时断点行成为当前行,但并未被执行。继续执行有两种方式。一种是单步方式,即逐条语句执行。这可以使用S命令完成:s第二种是使用c或C命令。一个最简单的c命令将使sdb从当前行把程序执行到下一个断点处。在c命令中还可以临时设置“断点”,如8c.5、关联命令我们可以告诉

24、sdb在使用到某种情况下暂停下来,完成某些操作之后继续执行。例如:* 7b t; i/;c将使得sdb在当前文件的第7行设置一个断点,然后每当遇到该断点时都显示函数调用栈(t)、变量i的值(i/),并继续程序的执行(c)。上述命令的一种变化形式是a(Announce命令)。6、变量的监视sdb提供了一种被成为“观察点”(Watch)的机制。借此机制,我们可以监视变量值得变化或某些地址的内容的变化。例如:* i $m可用于设置对某个变量的观察点。此处变量i为被监视的变量。* 0 x00400000:m则可将地址0 x00400000 处设置成观察点,而0 x00400000将成为被监视的地址。7

25、、sdb还支持其他一些命令。使用这些命令,可以完成其他一些辅助性的工作。如:. !Shell Command此命令可以使sdb去执行指定的Shell Command。这里Shell Command是一个合法命令。例如可以输入:* ! ls -lsdb将执行指定的ls -l 命令,并将其输出显示出来。 FileName 指示sdb从文件FileName中读取sdb调试命令,并且逐个执行之。SomeString 指示sdb显示出某个字符串。常用此命令给出某些提示信息,k 此命令将使当前对程序的调试终止,之后仍可用r命令重新启动被调试的程序。如: q此命令将使sdb停止其自身的运行而返回至原Shel

26、l提示符下。在调试完程序之后一般都要使用此命令。常用gdb调试命令包括:命令名命令名命令功能描述命令功能描述file装入想要调试的可执行文件。kill 终止正在调试的程序。list 执行一行源代码但不进入函数内部。next 执行下一行源代码但不进入函数内部。step 执行一行源代码而且进入函数内部。run 执行当前被调试的程序。quit 终止 gdb。watch 能够监视一个变量的值,无论它何时被改变。break 在代码里设置断点,使程序执行到这里时被挂起。make 在能够不退出 gdb情况下可以重新产生可执行文件。shell 在不离开 gdb的情况下可以执行 UNIX的 shell 命令。程

27、序执行流程控制:主要指断点的设置、指令的单步或连续执行等。 变量的检查: 主要指显示或修改变量的值。这里的变量还包括内存的某块存储区域以及寄存器等。 函数调用栈的显示: 指的是当前程序执行过程中函数的调用关系。帮助从总体上把握程序的执行情况。 汇编语言级的调试:经过编译之后,一条高级语言语句将被编译成多条功能与之等效的汇编指令。在需要更仔细地观察程序执行情况时,就能够使用调试工具进行汇编级的调试。 源程序的显示: 主要使调试人员能够方便地观察已经或将要被执行的指令到底是些什么指令程序调试中所用到的一些技术程序调试中所用到的一些技术3. 链接特殊函数库链接特殊函数库/*filename is t

28、emp.c */ # include int main(int argc,char *argv) double value; value=log(argc); printf(Value:%f n,value); 用命令:gcc o temp temp.c 编译时出错。修改命令: gcc o temp temp.c lm这里指明编译时与数学库libm.a相链接,则可正确编译。假设有程序temp.c如下:链接实际上是指将在一个模块中引用的符号与它在另一个模块中的定义相链接的过程。分为动态链接和静态链接两种方式。链接程序搜索程序中的每一个模块,包括所用到的每一个库文件,以在这些文件中寻找在某个模块中

29、没有定义的外部符号的定义。如果没有找到某个被引用的符号的定义,链接程序将报告错误。此时可执行文件的创建将会失败。关于关于链接链接对于静态链接和动态链接,其区别主要在于搜索到某个符号的定义后链接程序所做的不同工作:所做工作所做工作外部引用及定义链外部引用及定义链接的时间接的时间静态链接拷贝目标代码文件创建动态链接标记目标代码位置程序执行main.c中所调用的printf(),这个函数是在自己的程序中所没有定义的。这是标准C库所提供的。标准的C函数库有动态和静态两个不同的版本,其文件名分别是libc.so和libc.a,分别用于动态链接和静态链接。缺省情况下,链接程序将对标准C库函数调用进行动态链

30、接(使用libc.so),也即所调用的函数将在运行时与程序相链接。cc自动对标准C库的动态链接是下述约定为基础的:根据约定,共享对象或动态链接库的名称,前缀是lib而后缀是.so;档案库或者静态链接库,前缀为lib而后缀是.a。因此标准C库的共享版本的名称将是libc.so;而静态版本的名称则是libc.a。cc命令的-l选项能够识别上述约定缺省情况下,链接程序将优先查找同一目录下的动态库版本libx.so,不成功时才选择静态库libx.a。缺省情况下,链接程序将在系统的标准位置(/usr/ccs/lib和/usr/lib目录下)按上述顺序搜索所需的库。由编译系统提供的标准库一般被放在/usr

31、/ccs/lib目录下。 在这些约定的基础上,我们可以更明确地讲,缺省的cc命令行将引导链接程序搜索/usr/ccs/lib/libc.so,而不是它所对应的静态库。在程序比较复杂的情况下,一个程序可能就不是仅仅调用了标准C库中的函数了。例如,对于用到了数学运算sin(),cos()这类函数的程序,它就可能需要同数学函数库链接。链接程序将在标准位置查找libm.a库函数。当然这需要在cc命令行中加上一个-l选项,如下所示:$ cc file.c file2.c -lm-l选项在命令行中的位置很重要。例如:$ cc -dn file1.c -lm file2.c这样链接程序对libm.a的搜索只是为了解决file1.c中对数学函数的调用。静态库和动态库的建立静态库收集了一系列的目标文件。这些目标文件就是由CC对函数的源代码编译生成的。因此,静态库的生成方法实际上可分成两步:1.将各函数代码所在地源文件编译成目标文件。例如,对于前面的m

温馨提示

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

评论

0/150

提交评论