logo资料库

apue中文.pdf

第1页 / 共552页
第2页 / 共552页
第3页 / 共552页
第4页 / 共552页
第5页 / 共552页
第6页 / 共552页
第7页 / 共552页
第8页 / 共552页
资料共552页,剩余部分请下载后查看
001
第1 章U N I X 基础知识
1.1 引言
1.2 登录
1.2.1 登录名
1.2.2 shell
1.3 文件和目录
1.3.1 文件系统
1.3.2 文件名
1.3.3 路径名
1.3.4 工作目录
1.3.5 起始目录
1.4 输入和输出
1.4.1 文件描述符
1.4.2 标准输入、标准输出和标准出错
1.4.3 不用缓存的I / O
1.4.4 标准I / O
1.5 程序和进程
1.5.1 程序
1.5.2 进程和进程I D
1.5.3 进程控制
1.6 ANSI C
1.6.1 函数原型
1.6.2 类属指针
1.6.3 原始系统数据类型
1.7 出错处理
1.8 用户标识
1.8.1 用户I D
1.8.2 组I D
1.8.3 添加组I D
1.9 信号
1.10 UNIX 时间值
1 . 11 系统调用和库函数
1.12 小结
002
第2 章U N I X 标准化及实现
2.1 引言
2.2 UNIX 标准化
2.2.1 ANSI C
2.2.2 IEEE POSIX
2.2.3 X/Open XPG3
2.2.4 FIPS
2.3 UNIX 实现
2.3.1 SVR4
2.3.2 4.3+BSD
2.4 标准和实现的关系
2.5 限制
2.5.1 ANSI C 限制
2.5.2 POSIX 限制
2.5.3 XPG3 限制
2.5.4 sysconf 、pathconf 和fpathconf 函数
2.5.5 FIPS 151-1 要求
2.5.6 限制总结
2.5.7 未确定的运行时间限制
2.6 功能测试宏
2.7 基本系统数据类型
2.8 标准之间的冲突
2.9 小结
003
第3 章文件I / O
3.1 引言
3.2 文件描述符
3.3 open 函数
3.4 creat 函数
3.5 close 函数
3.6 lseek 函数
3.7 read 函数
3.8 write 函数
3.9 I/O 的效率
3.10 文件共享
3.11 原子操作
3.11.1 添加至一个文件
3.11.2 创建一个文件
3.12 dup 和d u p 2 函数
3.13 fcntl 函数
3.14 ioctl 函数
3.15 /dev/fd
3.16 小结
004
第4 章文件和目录
4.1 引言
4.2 stat 、fstat 和lstat 函数
4.3 文件类型
4.4 设置-用户- I D 和设置-组- I D
4.5 文件存取许可权
4.6 新文件和目录的所有权
4.7 access 函数
4.8 umask 函数
4.9 chmod 和f c h m o d 函数
4.10 粘住位
4 . 11 chown, fchown 和l c h o w n 函数
4.12 文件长度
4.13 文件截短
4.14 文件系统
4.15 link,unlink,remove 和r e n a m e 函数
4.16 符号连接
4.17 symlink 和r e a d l i n k 函数
4.18 文件的时间
4.19 utime 函数
4.20 mkdir 和r m d i r 函数
4.21 读目录
4.22 chdir, fchdir 和getcwd 函数
4.23 特殊设备文件
4.24 sync 和f s y n c 函数
4.25 文件存取许可权位小结
4.26 小结
005
第5 章标准I/O 库
5.1 引言
5.2 流和F I L E 对象
5.3 标准输入、标准输出和标准出错
5.4 缓存
5.5 打开流
5.6 读和写流
5.6.1 输入函数
5.6.2 输出函数
5.7 每次一行I / O
5.8 标准I / O 的效率
5.9 二进制I / O
5.10 定位流
5.11 格式化I / O
5.11.1 格式化输出
5.11.2 格式化输入
5.12 实现细节
5.13 临时文件
5.14 标准I / O 的替代软件
5.15 小结
006
第6 章系统数据文件和信息
6.1 引言
6.2 口令文件
6.3 阴影口令
6.4 组文件
6.5 添加组I D
6.6 其他数据文件
6.7 登录会计
6.8 系统标识
6.9 时间和日期例程
6.10 小结
007
第7 章U N I X 进程的环境
7.1 引言
7.2 main 函数
7.3 进程终止
7.3.1 exit 和_ e x i t 函数
7.3.2 atexit 函数
7.4 命令行参数
7.5 环境表
7.6 C 程序的存储空间布局
7.7 共享库
7.8 存储器分配
7.9 环境变量
7.10 setjmp 和l o n g j m p 函数
7.10.1 自动、寄存器和易失变量
7.10.2 自动变量的潜在问题
7.11 getrlimit 和s e t r l i m i t �
7.12 小结
008
第8 章进程控制
8.1 引言
8.2 进程标识
8.3 fork 函数
8.4 vfork 函数
8.5 exit 函数
8.6 wait 和w a i t p i d 函数
8.7 wait3 和w a i t 4 函数
8.8 竞态条件
8.9 exec 函数
8.10 更改用户I D 和组I D
8.10.1 setreuid 和s e t r e g i d 函数
8.10.2 seteuid 和s e t e g i d 函数
8.10.3 组I D
8.11 解释器文件
8.12 system 函数
8.13 进程会计
8.14 用户标识
8.15 进程时间
8.16 小结
009
第9 章进程关系
9.1 引言
9.2 终端登录
9.2.1 4.3+BSD 终端登录
9.2.2 SVR4 终端登录
9.3 网络登录
9.3.1 4.3 +B S D 网络登录
9.3.2 SVR4 网络登录
9.4 进程组
9.5 对话期
9.6 控制终端
9.7 tcgetpgrp 和t c s e t p g r p 函数
9.8 作业控制
9.9 shell 执行程序
9.10 孤儿进程组
9.11 4.3+BSD 实现
9.12 小结
010
第1 0 章信号
10.1 引言
10.2 信号的概念
10.3 signal 函数
10.3.1 程序起动
10.3.2 进程创建
10.4 不可靠的信号
10.5 中断的系统调用
10.6 可再入函数
10.7 SIGCLD 语义
10.8 可靠信号术语和语义
10.9 kill 和r a i s e 函数
10.10 alarm 和p a u s e 函数
1 0.11 信号集
10.12 sigprocmask 函数
10.13 sigpending 函数
10.14 sigaction 函数
10.15 sigsetjmp 和s i g l o n g j m p 函数
10.16 sigsuspend 函数
10.17 abort 函数
10.18 system 函数
10.19 sleep 函数
10.20 作业控制信号
10.21 其他特征
10.21.1 信号名字
10.21.2 SVR4 信号处理程序的附加参数
10.21.3 4.3+BSD 信号处理程序的附加参数
10.22 小结
011
第11 章终端I / O
11.1 引言
11.2 综述
11.3 特殊输入字符
11.4 获得和设置终端属性
11.5 终端选择标志
11.6 stty 命令
11.7 波特率函数
11.8 行控制函数
11.9 终端标识
11.10 规范方式
11 . 11 非规范方式
11.12 终端的窗口大小
11.13 termcap,terminfo 和c u r s e s
11.14 小结
012
第1 2 章高级I / O
12.1 引言
12.2 非阻塞I / O
12.3 记录锁
12.3.1 历史
12.3.2 fcntl 记录锁
12.3.3 锁的隐含继承和释放
12.3.4 4.3+BSD 的实现
12.3.5 建议性锁和强制性锁
12.4 流
12.4.1 流消息
12.4.2 putmsg 和p u t p m s g 函数
12.4.3 流ioctl 操作
12.4.4 write 至流设备
12.4.5 写方式
12.4.6 getmsg 和g e t p m s g 函数
12.4.7 读方式
12.5 I/O 多路转接
12.5.1 select 函数
12.5.2 poll 函数
12.6 异步I / O
12.6.1 SVR4
12.6.2 4.3+BSD
12.7 readv 和w r i t e v 函数
12.8 readn 和w r i t e n 函数
12.9 存储映射I / O
12.10 小结
013
第1 3 章精灵进程
13.1 引言
13.2 精灵进程的特征
13.3 编程规则
13.4 出错记录
13.4.1 SVR4 流l o g 驱动程序
13.4.2 4.3+BSD syslog 设施
13.5 客户机-服务器模型
13.6 小结
014
第1 4 章进程间通信
14.1 引言
14.2 管道
14.3 popen 和p c l o s e 函数
14.4 协同进程
14.5 FIFO
14.6 系统V IPC 三种系统V IPC :消息
14.6.1 标识符和关键字
14.6.2 许可权结构
14.6.3 结构限制
14.6.4 优点和缺点
14.7 消息队列
14.8 信号量
14.9 共享存储
14.10 客户机-服务器属性
1 4.11 小结
015
第1 5 章高级进程间通信
15.1 引言
15.2 流管道
15.3 传送文件描述符
15.3.1 SVR4
15.3.2 4.3BSD
15.3.3 4.3+BSD
15.4 open 服务器第1 版
15.5 客户机-服务器连接函数
15.5.1 SVR4
15.5.2 4.3+BSD
15.6 open 服务器第2 版
15.7 小结
016
第1 6 章数据库函数库
16.1 引言
16.2 历史
16.3 函数库
16.4 实现概述
16.5 集中式或非集中式
16.6 并发
16.6.1 粗锁
16.6.2 细锁
16.7 源码
16.8 性能
16.8.1 单进程的结果
16.8.2 多进程的结果
16.9 小结
017
第1 7 章与PostScript 打印机通信
17.1 引言
17.2 PostScript 通信机制
17.3 假脱机打印
17.4 源码
17.5 小结
018
第1 8 章调制解调器拨号器
18.1 引言
18.2 历史
18.3 程序设计
18.4 数据文件
18.5 服务器设计
18.6 服务器源码
18.7 客户机设计
18.7.1 终端行规程
18.7.2 一个进程还是两个进程
18.8 客户机源码
18.9 小结
019
第1 9 章伪终端
19.1 引言
19.2 概述
19.2.1 网络登录服务器
19.2.2 script 程序
19.2.3 expect 程序
19.2.4 运行协同进程
19.2.5 观看长时间运行程序的输出
19.3 打开伪终端设备
19.3.1 SVR4
19.3.2 4.3+BSD
19.4 pty_fork 函数
19.5 pty 程序
19.6 使用p t y 程序
19.6.1 utmp 文件
19.6.2 作业控制交互
19.6.3 检查长时间运行程序的输出
19.6.4 script 程序
19.6.5 运行协同进程
19.6.6 用非交互模式驱动交互式程序
19.7 其他特性
19.7.1 打包模式
19.7.2 远程模式
19.7.3 窗口大小变化
19.7.4 信号发生
19.8 小结
020
附录A 函数原型
021
附录B 其他源代码
B.1 头文件
B.2 标准出错处理例程
022
附录C 习题答案
第1 章
第2 章
第3 章
第4 章
第5 章
第6 章
第7 章
第8 章
第9 章
第10章
第11章
第12章
第13章
第14章
第15章
第16章
第17章
第18章
第19章
023
参考书目
下载 1.1 引言 第1章 U N I X基础知识 所有操作系统都向它们运行的程序提供服务。典型的服务有执行新程序、打开文件、读文 件、分配存储区、获得当前时间等等,本书集中阐述了 U N I X操作系统各种版本所提供的服务。 以严格的步进方式、不超前引用尚未说明过的术语的方式来说明 U N I X几乎是不可能的(可 能也会是令人厌烦的 )。本章从程序设计人员的角度快速浏览 U N I X,并对书中引用的一些术语 和概念进行简要的说明并给出实例。在以后各章中,将对这些概念作更详细的说明。本章也对 不熟悉U N I X的程序设计人员简要介绍了 U N I X提供的各种服务。 1.2 登录 1.2.1 登录名 登录 U N I X 系统时,先键入登录名,然后键入口令。系统在其口令文件,通常是 / e t c / p a s s w d文件中查看登录名。口令文件中的登录项由 7个以冒号分隔的字段组成:登录名, 加密口令,数字用户 I D ( 2 2 4 ),数字组I D ( 2 0 ),注释字段,起始目录 ( / h o m e / s t e v e n s ),以及s h e l l 程序( / b i n / k s h )。 很多比较新的系统已将加密口令移到另一个文件中。第 6章将说明这种文件以及存取它们 的函数。 1.2.2 shell 登录后,系统先显示一些典型的系统信息,然后就可以向 s h e l l程序键入命令。s h e l l是一个 命令行解释器,它读取用户输入,然后执行命令,用户通常用终端,有时则通过文件 (称为 s h e l l脚本)向s h e l l进行输入。常用的 s h e l l有: • Bourne shell, /bin/sh • C shell, /bin/csh • KornShell, /bin/ksh 系统从口令文件中登录项的最后一个字段中了解到应该执行哪一个 s h e l l。 自V 7以来,Bourne shell得到了广泛应用,几乎每一个现有的U N I X系统都提供Bourne shell。 C shell是在伯克利开发的,所有 B S D版本都提供这种 s h e l l。另外, AT & T的系统V/386 R3.2和 S V R 4也提供C shell(下一章将对这些不同的U N I X版本作更多说明)。K o r n S h e l l是Bourne shell 的后继者,它由S V R 4提供。K o r n S h e l l在大多数U N I X系统上运行,但在 S V R 4之前,通常它需 要另行购买,所以没有其他两种 s h e l l流行。 本书将使用很多 s h e l l实例,以执行已开发的程序,其中将应用 Bourne shell和K o r n S h e l l都 具有的功能。
2 U N I X环境高级编程 下载 Bourne shell是Steve Bourne在贝尔实验室中开发的,其控制流结构使人想起 Algol 68。C shell是在伯克利由Bill Joy完成的,其基础是第6版s h e l l(不是B o u r n e s h e l l)。其控制结构很像C语言,它支持一些Bourne shell没有提供的功能,如作业 控制,历史机制和命令行编辑。 K o r n S h e l l是David Korn在贝尔实验室中开发的, 它兼容Bourne shell,并且也包含了使 C shell非常流行的一些功能,如作业控制、 命令行编译等。 本书将使用这种形式的注释来描述历史,并对不同的 U N I X实现进行比较。当 我们了解了历史缘由后,采用某种特定实现技术的原因将变得清晰起来。 1.3 文件和目录 1.3.1 文件系统 U N I X文件系统是目录和文件的一种层次安排,目录的起点称为根 ( r o o t ),其名字是一个 字符/。 目录(d i r e c t o r y)是一个包含目录项的文件,在逻辑上,可以认为每个目录项都包含一个 文件名,同时还包含说明该文件属性的信息。文件属性是:文件类型,文件长度,文件所有者, 文件的许可权(例如,其他用户能否能访问该文件),文件最后的修改时间等。 s t a t和f s t a t函数 返回一个包含所有文件属性的信息结构。第 4章将详细说明文件的各种属性。 1.3.2 文件名 目录中的各个名字称为文件名( f i l e n a m e)。不能出现在文件名中的字符只有两个,斜线 ( / ) 和空操作符(n u l l)。斜线分隔构成路径名 (在下面说明)的各文件名,空操作符则终止一个路径 名。尽管如此,好的习惯是只使用印刷字符的一个子集作为文件名字符 (只使用子集的理由是: 如果在文件名中使用了某些 s h e l l特殊字符,则必须使用s h e l l的引号机制来引用文件名)。 当创建一个新目录时,自动创建了两个文件名: . (称为点)和. . (称为点-点)。点引用当前目 录,点-点则引用父目录。在最高层次的根目录中,点 -点与点相同。 某些U N I X文件系统限制文件名的最大长度为 1 4个字符,B S D版本则将这种限制扩展为 2 5 5 个字符。 1.3.3 路径名 0个或多个以斜线分隔的文件名序列 (可以任选地以斜线开头 )构成路径名( p a t h n a m e),以 斜线开头的路径名称为绝对路径名( absolute pathname ),否则称为相对路径名( r e l a t i v e p a t h n a m e)。 实例 不难列出一个目录中所有文件的名字,程序 1 - 1是l s ( 1 )命令的主要实现部分 程序1-1 列出一个目录中的所有文件
下载 第 1章 U N I X基础知识 3 l s ( 1 )这种表示方法是U N I X的惯用方法,用以引用 U N I X手册集中的一个特定项。它引用第 一部分中的 l s项,各部分通常用数字 1至8表示,在每个部分中的各项则按字母顺序排列。假定 你有一份所使用的 U N I X系统的手册。 早期的U N I X系统把8个部分都集中在一本手册中,现在的趋势是把这些部分 分别安排在不同的手册中:有用户专用手册,程序员专用手册,系统管理员专用 的手册等等。 某些U N I X系统把一个给定部分中的手册页又用一个大写字母进一步分成若干 小部分,例如,AT & T〔1 9 9 0 e〕中的所有标准I / O函数都被指明在3 S部分中,例如 f o p e n ( 3 S )。 某些U N I X系统,例如以 X e n i x为基础的系统,不是采用数字将手册分成若干 部分,而是用C表示命令(第1部分),S表示服务(通常是第2、3部分)等等。 如果你有联机手册,则可用下面的命令查看 l s命令手册页: man 1 ls 程序1 - 1只打印一个目录中各个文件的名字,不显示其他信息,如若该源文件名为 m y l s . c , 则可以用下面的命令对其进行编译,编译的结果送入系统默认名为 a . o u t的可执行文件名: cc myls.c 某种样本输出是: $ a.out /dev . . . M A K E D E V c o n s o l e t t y m e m k m e m n u l l 此处略去多行
4 U N I X环境高级编程 p r i n t e r $ a . o u t / v a r / s p o o l / m q u e u e c a n ' t o p e n / v a r / s p o o l / m q u e u e : P e r m i s s i o n d e n i e d $ a.out /dev/tty c a n ' t o p e n / d e v / t t y : N o t a d i r e c t o r y 下载 本书将以这种方式表示输入的命令以及其输出:输入的字符以粗体表示,程序输出则以另 一种字体表示。如果欲对输出添加注释,则以中文宋体表示,输入之前的美元符号 ( $ )是s h e l l打 印的提示符,本书将s h e l l提示符显示为$。 注意,列出的目录项不是以字母顺序排列的, l s命令则一般按字母顺序列出目录项。 在这2 0行的程序中,有很多细节需要考虑: • 首先,其中包含了一个头文件 o u r h d r. h。本书中几乎每一个程序都包含此头文件。它包含 了某些标准系统头文件,定义了许多常数及函数原型,这些都将用于本书的各个实例中,附录 B列出了常用头文件。 • main函数的说明使用了ANSI C 标准所支持的新风格(下一章将对 ANSI C作更多说明)。 • 取命令行的第1个参数a rg v〔1〕作为列出的目录名。第 7章将说明 m a i n函数如何被调用, 程序如何存取命令行参数和环境变量。 • 因为各种不同U N I X系统的目录项的实际格式是不一样的,所以使用函数 o p e n d i r, readdir 和c l o s e d i r处理目录。 • opendir函数返回指向 D I R结构的指针,并将该指针传向 r e a d d i r函数。我们并不关心 D I R 结构中包含了什么。然后,在循环中调用 r e a d d i r来读每个目录项。它返回一个指向 d i r e n t结 构的指针,而当目录中已无目录项可读时则返回 n u l l指针。在 d i r e n t结构中取出的只是每个 目录项的名字 ( d _ n a m e )。使用该名字,此后就可调用 s t a t函数(见4 . 2节)以决定该文件的所有 属性。 • 调用了两个自编的函数来对错误进行处理:e r r _ s y s和e r r _ q u i t。从上面的输出中可以看到, e r r _ s y s函数打印一条消息(“Permission denied(许可权拒绝 )”或“Not a directory(不是一个目 录)”),说明遇到了什么类型的错误。这两个出错处理函数在附录 B中说明, 1 . 7节将更多地叙 述出错处理。这两个出错处理函数在附录 B中说明1 . 7节将更详细地叙述出错处理。 • 当程序将结束时,它以参数 0调用函数e x i t。函数e x i t终止程序。按惯例,参数 0的意思是 正常结束,参数值1~2 5 5则表示出错。8 . 5节将说明一个程序(例如s h e l l或我们所编写的程序)如 何获得它所执行的另一个程序的 e x i t状态。 1.3.4 工作目录 每个进程都有一个工作目录 (working directory,有时称为当前工作目录 (current working d i r e c t o r y ) )。所有相对路径名都从工作目录开始解释。进程可以用 c h d i r函数更改其工作目录。 例如,相对路径名 d o c / m e m o / j o e指的是文件 j o e,它在目录m e m o中,而m e m o又在目录 d o c 中,d o c则应是工作目录中的一个目录项。从该路径名可以看出, d o c和m e m o都应当是目录, 但是却不清楚 j o e是文件还是目录。路径名 / u r s / l i b / l i n t是一个绝对路径名,它指的是文件 (或目 录) lint,而l i n t在目录l i b中,l i b则在目录u s r中,u s r则在根目录中。 1.3.5 起始目录 登录时,工作目录设置为起始目录 (home directory),该起始目录从口令文件(见1 . 2节)中
第 1章 U N I X基础知识 5 下载 的登录项中取得。 1.4 输入和输出 1.4.1 文件描述符 文字描述符是一个小的非负整数,内核用以标识一个特定进程正在存访的文件。当内核打 开一个现存文件或创建一个新文件时,它就返回一个文件描述符。当读、写文件时,就可使 用它。 1.4.2 标准输入、标准输出和标准出错 按惯例,每当运行一个新程序时,所有的 s h e l l都为其打开三个文件描述符:标准输入、标 准输出以及标准出错。如果像简单命令 l s那样没有做什么特殊处理,则这三个描述符都连向终 端。大多数s h e l l都提供一种方法,使任何一个或所有这三个描述符都能重新定向到某一个文件, 例如: l s > f i l e . l i s t 执行l s命令,其标准输出重新定向到名为 f i l e . l i s t的文件上。 1.4.3 不用缓存的 I / O 函数o p e n、r e a d、w r i t e、l s e e k以及c l o s e提供了不用缓存的 I / O。这些函数都用文件描述符 进行工作。 实例 如果愿意从标准输入读,并写向标准输出,则程序 1 - 2可用于复制任一U N I X文件。 程序1-2 将标准输入复制到标准输出 头文件 < u n i s t d . h > ( o u r h d r. h中包含了此头文件 )及两个常数 S T D I N _ F I L E N O和S T D O U T _ F I L E N O是P O S I X标准的一部分(下一章将对此作更多的说明)。很多U N I X系统服务的函数原 型,例如我们调用的r e a d和w r i t e都在此头文件中。函数原型也是 ANSI C 标准的一部分,本章的
6 U N I X环境高级编程 稍后部分将对此作更多说明。 下载 两个常数S T D I N _ F I L E N O和S T D O U T _ F I L E N O定义在< u n i s t d . h >头文件中,它们指定了标 准输入和标准输出的文件描述符。它们的典型值是 0和1,但是为了可移植性,我们将使用这些 新名字。 3 . 9节将详细讨论B U F F S I Z E常数,说明各种不同的值将如何影响程序的效率。但是不管该 常数的值如何,此程序总能复制任一 U N I X文件。 r e a d函数返回读得的字节数,此值用作要写的字节数。当到达文件的尾端时, r e a d返回0, 程序停止执行。如果发生了一个读错误, r e a d返回-1。出错时大多数系统函数返回-1。 如果编译该程序,其结果送入标准的 a . o u t文件,并以下列方式执行它: a . o u t > d a t a 那么,标准输入是终端,标准输出则重新定向至文件 d a t a,标准出错也是终端。如果此输出文 件并不存在,则 s h e l l创建它。 第3章将更详细地说明不用缓存的 I / O函数。 1.4.4 标准I / O 标准I / O函数提供一种对不用缓存的I / O函数的带缓存的界面。使用标准 I / O可无需担心如何 选取最佳的缓存长度,例如程序 1 - 2中的B U F F S I Z E常数。另一个使用标准 I / O函数的优点与处 理输入行有关 (常常发生在U N I X的应用中)。例如,f g e t s函数读一完整的行,而另一方面, r e a d 函数读指定字节数。 我们最熟悉的标准 I / O函数是p r i n t f。在调用p r i n t f的程序中,总是包括< s t d i o . h > (通常包括在 o u r h d r. h中),因为此头文件包括了所有标准 I / O函数的原型。 实例 程序1 - 3的功能类似于调用 r e a d和w r i t e的前一个程序 1 - 2,5 . 8节将对程序 1 - 3作更详细的说 明。它将标准输入复制到标准输出,于是也就能复制任一 U N I X文件。 程序1-3 用标准I / O将标准输入复制到标准输出 函数g e t c一次读 1个字符,然后 p u t c将此字符写到标准输出。读到输入的最后 1个字节时, g e t c返回常数E O F。标准输入、输出常数 s t d i n和s t d o u t定义在头文件< s t d i o . h >中,它们分别表示 标准输入和标准输出文件。
下载 1.5 程序和进程 1.5.1 程序 第 1章 U N I X基础知识 7 程序(p r o g r a m)是存放在磁盘文件中的可执行文件。使用 6个e x e c函数中的一个由内核将 程序读入存储器,并使其执行。 8 . 9节将说明这些e x e c函数。 1.5.2 进程和进程 I D 程序的执行实例被称为进程( p r o c e s s)。本书的每一页几乎都会使用这一术语。某些操作 系统用任务表示正被执行的程序。 每个U N I X进程都一定有一个唯一的数字标识符,称为进程 I D(process ID)。进程I D总是 一非负整数。 实例 程序1 - 4用于打印进程I D。 程序1-4 打印进程I D 如果要编译该程序,其结果送入 a . o u t文件,然后执行它,则有: $ a . o u t h e l l o w o r l d f r o m p r o c e s s I D 8 5 1 $ a . o u t h e l l o w o r l d f r o m p r e c e s s I D 8 5 4 此程序运行时,它调用函数g e t p i d得到其进程I D。 1.5.3 进程控制 有三个用于进程控制的主要函数: f o r k、e x e c和w a i t p i d(e x e c函数有六种变体,但经常把 它们统称为e x e c函数)。 实例 程序1-5 从标准输入读命令并执行
8 U N I X环境高级编程 下载 U N I X的进程控制功能可以用一个较简单的程序(见程序 1 - 5)说明,该程序从标准输入读 命令,然后执行这些命令。这是一个类似于 s h e l l程序的基本实施部分。在这个 3 0行的程序中, 有很多功能需要思考: • 用标准I / O函数f g e t s从标准输入一次读一行,当键入文件结束字符(通常是 C t r l - D)作为 行的第1个字符时,f g e t s返回一个n u l l指针,于是循环终止,进程也就终止。第 11章将说明所有 特殊的终端字符 (文件结束、退格字符、整行擦除等等 ),以及如何改变它们。 • 因为f g e t s返回的每一行都以新行符终止,后随一个 n u l l字节,故用标准C函数s t r l e n计算此 字符串的长度,然后用一个 n u l l字节替换新行符。这一操作的目的是因为 e x e c l p函数要求的是 以n u l l结束的参数,而不是以新行符结束的参数。 • 调用f o r k创建一个新进程。新进程是调用进程的复制品,故称调用进程为父进程,新创 建的进程为子进程。f o r k对父进程返回新子进程的非负进程 I D,对子进程则返回0。因为f o r k创 建一新进程,所以说它被调用一次 (由父进程),但返回两次(在父进程中和在子进程中)。 • 在子进程中,调用 e x e c l p以执行从标准输入读入的命令。这就用新的程序文件替换了子 进程。f o r k和跟随其后的e x e c的组合是某些操作系统所称的产生一个新进程。在 U N I X中,这两 个部分分成两个函数。第8章将对这些函数作更多说明。 • 子进程调用 e x e c l p执行新程序文件,而父进程希望等待子进程终止,这一要求由调用 w a i t p i d实现,其参数指定要等待的进程 (在这里, p i d参数是子进程 I D )。w a i t p i d函数也返回子 进程的终止状态( s t a t u s变量)。在此简单程序中,没有使用该值。如果需要,可以用此值精确地 确定子进程是如何终止的。 • 该程序的最主要限制是不能向执行的命令传递参数。例如不能指定列出的目录名,只能 对工作目录执行l s命令。为了传递参数,先要分析输入行,然后用某种约定把参数分开 (很可能 使用空格或制表符),然后将分隔后的各个参数传递给 e x e c l p函数。尽管如此,此程序仍可用来 说明U N I X的进程控制功能。 如果运行此程序,则得到下列结果。注意,该程序使用了一个不同的提示符 ( % )。
分享到:
收藏