目 录
第一章 Unix 基础.................................................................................................................................1
1、Unix 手册页......................................................................................................................................1
2、系统调用与库函数............................................................................................................................2
3、文件和目录.......................................................................................................................................2
4、输入和输出.......................................................................................................................................3
5、程序与进程.......................................................................................................................................3
6、程序线程...........................................................................................................................................3
7、异步、并发、通信............................................................................................................................3
8、出错处理...........................................................................................................................................4
9、Unix 用户和用户标识........................................................................................................................4
10、信号................................................................................................................................................4
11、Unix 系统时间.................................................................................................................................5
第二章 Unix 标准化及实现..................................................................................................................6
1、主要标准...........................................................................................................................................6
2、主要 Unix 系统实现简介...................................................................................................................7
3、系统资源限制...................................................................................................................................9
4、POSIX 选项.....................................................................................................................................10
5、功能测试宏.....................................................................................................................................10
6、Unix 的基本系统数据类型..............................................................................................................10
第三章 文件 I/O.................................................................................................................................11
1、文件描述符 file descriptor..............................................................................................................11
2、打开文件:open 函数.....................................................................................................................11
3、创建新文件:creat 函数..................................................................................................................12
4、关闭文件:close 函数.....................................................................................................................12
5、定位文件:lseek 函数.....................................................................................................................12
6、读文件数据到缓冲区(输入操作):read 函数..............................................................................12
7、从缓冲区写数据到文件(输出操作):write 函数.........................................................................13
8、定位同时读写文件的原子操作:pread 和 pwrite 函数....................................................................13
9、复制文件描述符:dup 和 dup2 函数...............................................................................................13
10、更新到实际文件:sync、fsync 和 fdatasync 函数..........................................................................14
11、已打开文件状态的更改:fcntl 函数..............................................................................................14
12、ioctl 函数......................................................................................................................................14
第四章 文件和目录............................................................................................................................15
1、stat、fstat 和 lstat 函数...................................................................................................................15
2、文件访问权限.................................................................................................................................16
3、文件的尺寸.....................................................................................................................................17
4、Unix 文件系统的基本概念..............................................................................................................17
5、硬链接............................................................................................................................................18
6、符号链接.........................................................................................................................................18
7、文件重命名.....................................................................................................................................19
8、文件的时间.....................................................................................................................................19
9、目录访问.........................................................................................................................................20
10、设备文件.......................................................................................................................................21
11、其它文件.......................................................................................................................................21
第五章 标准 I/O 库............................................................................................................................22
1、文件流和 FILE 指针.........................................................................................................................22
2、stdin、stdout 和 stderr...................................................................................................................22
3、标准 I/O 的缓冲方式.......................................................................................................................22
4、对文件流进行打开、读写和关闭....................................................................................................23
5、文件流的定位.................................................................................................................................25
6、文件流 I/O 的格式化函数................................................................................................................26
7、关联文件流到文件描述符(非 ISO C)...........................................................................................26
8、创建临时文件.................................................................................................................................26
第六章 系统数据文件和信息.............................................................................................................28
1、主要的系统数据..............................................................................................................................28
2、utmp 文件和 wtmp 文件.................................................................................................................29
3、系统标识 uname.............................................................................................................................29
4、时间和日期.....................................................................................................................................29
5、proc 文件系统.................................................................................................................................31
第七章 进程环境...............................................................................................................................32
1、进程的启动和终止..........................................................................................................................32
2、命令行参数和环境变量...................................................................................................................33
3、Unix 中 C 程序的存储空间基本布局................................................................................................35
4、设置和获取系统资源限制...............................................................................................................36
第八章 进程控制...............................................................................................................................38
1、进程标识符 PID 的概念...................................................................................................................38
2、fork(2)函数....................................................................................................................................38
3、取子进程终止状态的 wait 家族函数................................................................................................39
4、exec 家族函数.................................................................................................................................41
5、一个例子:exec 一个脚本解释器文件.............................................................................................43
6、setuid(2)和 setgid(2)......................................................................................................................43
7、system(3)函数................................................................................................................................44
8、用于调度进程的函数.......................................................................................................................44
第九章 进程关系...............................................................................................................................45
1、进程组(process group)...................................................................................................................45
2、会话(session)..................................................................................................................................45
3、控制终端(controlling terminal)......................................................................................................45
4、作业控制(job control).....................................................................................................................46
6、孤儿进程组(orphaned process groups)...........................................................................................46
第十章 信号.......................................................................................................................................47
1、基本概念.........................................................................................................................................47
2、常用信号略述.................................................................................................................................48
3、signal(2)函数..................................................................................................................................48
4、早期 UNIX 实现的不可靠信号机制..................................................................................................49
5、系统调用的自动重启动问题............................................................................................................49
6、可重入函数与异步信号安全............................................................................................................49
7、SIGCHLD 与 SIGCLD 信号...............................................................................................................50
8、产生信号:kill 和 raise 函数............................................................................................................50
9、alarm 和 pause................................................................................................................................51
10、信号集及其处理函数.....................................................................................................................51
11、sigaction 函数...............................................................................................................................52
12、sigsetjmp 和 siglongjmp 函数........................................................................................................53
13、实例:在 abort、system 及 sleep 函数的实现中使用信号机制......................................................53
14、作业控制信号...............................................................................................................................53
15、信号值与信号名字之间的转换......................................................................................................53
第十一章 线程...................................................................................................................................54
1、线程 ID 类型的访问方法.................................................................................................................54
2、线程的创建.....................................................................................................................................54
3、线程的终止.....................................................................................................................................55
4、线程的同步.....................................................................................................................................56
第十二章 线程控制............................................................................................................................60
1、线程属性对象.................................................................................................................................60
2、线程同步对象的属性.......................................................................................................................61
3、线程的重入与线程安全...................................................................................................................62
4、线程私有数据.................................................................................................................................63
5、取消选项.........................................................................................................................................64
6、线程与信号.....................................................................................................................................64
7、线程和 fork.....................................................................................................................................65
8、线程和 I/O......................................................................................................................................66
第十三章 守护进程............................................................................................................................67
1、设计一个良好的守护进程的一般编程规则......................................................................................67
2、系统日志机制.................................................................................................................................68
3、daemon(3)函数..............................................................................................................................70
4、守护进程设计的另外一些常见惯例.................................................................................................72
第十四章 高级 I/O.............................................................................................................................73
1、记录锁............................................................................................................................................73
2、SysV STREAMS 机制......................................................................................................................74
3、非阻塞 I/O......................................................................................................................................74
4、I/O 多路转接..................................................................................................................................75
5、异步 I/O..........................................................................................................................................76
6、readv(2)和 writev(2)......................................................................................................................77
7、存储映射 I/O..................................................................................................................................77
第十五章 进程间通信........................................................................................................................79
1、管道................................................................................................................................................79
2、popen 和 pclose..............................................................................................................................80
3、协同进程的概念..............................................................................................................................81
4、fifo..................................................................................................................................................81
5、XSI IPC...........................................................................................................................................81
6、以上几种进程间通信机制应用在 C/S 模型中的比较.......................................................................86
7、APUE2 对本章所述的几种进程间通信机制的建议..........................................................................87
第十六章 网络 IPC:套接字..............................................................................................................88
1、概述................................................................................................................................................88
2、套接字的创建和关闭.......................................................................................................................89
3、计算机字节顺序..............................................................................................................................90
4、套接字与进程地址标识的关联........................................................................................................90
5、基于套接字的数据传输...................................................................................................................92
6、书中实例的程序模型.......................................................................................................................93
7、带外数据及异步 IO.........................................................................................................................96
APUE读书笔记
最近花了近两个月的业余时间,仔细完整拜读了 APUE2 的前 1~16 章。获益匪浅 ,对 Unix 系统及
其编程又有了更深的理解。不愧“独具匠心”四字。以下将我的读书笔记整理出来。
本文档排版说明如下:
• 文件和目录使用等宽字体。如:
/etc/passwd
• 代码片段和命令行操作使用方框加等宽字体。如:
#define _POSIX_C_SOURCE 200112L
• 系统命令及其参数使用绿色等宽字体。如:
find(1)
• 英文名资料及函数名称使用斜体。如
Advanced Programming in UNIX Environment
• 中文名资料使用书名号标准。如
《深入理解 Linux 内核》
• 函数参数使用下划线表示。如
sockfd、flags
• 引用的参考资料及相关资源用超链接标注出处。如
Unix
• 除了引用资料文字本身外,本文档中全大写的 UNIX 特指合法拥有 UNIX®商标的商用级 UNIX。
仅首字母大写则泛指以 POSIX 标准为基础发布的 Unixlike 系统。
Unix 程序设计特指应用程序设计,即运行在用户地址空间的软件。书中也描述了一些系统实现的细
节。但内核空间的编程基本上是平台相关的,故本书不涉及内核编程部分。对于 Linux,可参考 Linux
Device Driver 一书。
全书所附程序清单代码可以在这里下载。
另外 www.unixcenter.net 提供了包括 Solaris、AIX、FreeBSD、Fedora、Ubuntu 等 Unix 主机的免费
使用,如果没有 Linux/Unix 环境,可以在该网站注册帐号并用 ssh 登录相应机器做上机练习,同时可以
更好的理解 POSIX 标准及不同的 Unix 平台下的差异。
第一章 Unix 基础
1、Unix 手册页
Unix 参考手册页是进行系统编程必备的参考工具。它通常通过 man 命令直接联机阅读。手册页通常
分为 9 节。采用“名称(章节号)”的方式来描述 Unix 术语时,表示此名称同时也是联机手册对应章节
号下的一个条目。例如“fork(2)”指系统调用库函数 fork,可以使用“man 2 fork”来查看其手册页。
以 Linux 为例,参考手册页各节内容如下:
第 1 节为系统命令手册。如 cp(1);
第 2 节为系统调用手册。如 read(2);
1
APUE读书笔记
第 3 节为库函数手册。如 malloc(3);
第 4 节为系统特殊文件手册。如 tty(4);
第 5 节为标准的系统资源文件(全局配置文件)手册。如 services(5);
第 6 节为游戏程序手册,包括屏保等各种图形化娱乐工具。如 glmatrix(6);
第 7 节为杂类手册,包括各类头文件和宏,如 socket.h(7);
第 8 节为系统管理工具,如 useradd(8);
第 9 节为内核例程。
工具 apropos(1)可以用于查找手册页的名字和介绍;导入脚本/etc/bash_completion 则可以
增强 shell 的制表键自动补全功能,在输入 man 后列出手册页清单;还可以使用我写的一个比较山寨的索
引工具。
重要的手册页软件包包括(包名因各 Unix 发行版而有所不同):manpages、manpages
dev、manpagesposix、manpagesposixdev。
2、系统调用与库函数
系统调用提供了用户程序访问内核的接口,用户程序通过执行系统调用间接的获取内核所管理资源
的访问权。执行系统调用时,程序控制权交给内核,内核在进程上下文中运行。
库函数通过包含相应的.h 头文件引用。用户程序可以通过调用操作系统提供的库函数间接进行系统
调用。如 printf(3)库函数,它除了管理缓冲区和格式化文本之外,执行了 write 系统调用访问文件。库函
数也可以由其它程序提供,例如 GTK 库等。用户也可以自己重新实现库函数接口以替代所提供的库函数
功能。
另一方面,系统调用实际上也以库函数的形式直接提供给用户程序,如 write(2)、fork(2)等。对用户
程序来说,不必专门区别那些是库函数、哪些是系统调用接口。
对于 x86 平台的 Linux,亦可以通过/usr/include/asm/unistd_32.h 查看其系统调用的接口。
3、文件和目录
Unix 系统将计算机中的大部分资源都抽象为文件的形式,这样我们就可以通过 open(2), read(2),
write(2)等函数去直接访问它们。
• 文件系统的结构:Unix 系统采用树状结构,全局具有唯一的一个根目录,通过“/”访问,除交换分
区外,其它文件系统均挂载在/或其子目录下作为子目录存在。
• 文件名:除字符“/”与“NUL”外,都可以作为 Unix 文件的文件名,但为访问方便起见,一般建议
采用可打印字符作为文件名,尽量不要使用 shell 和其它正则表达式的扩展字符,如*、?等。
• 路径名:访问一个文件可使用绝对路径(以/开头)或者相对路径(不以“/”起头的均被认作相对
路径)。
• 目录中的特殊文件“.”和“..”:“/”下的“.”“..”指向它自身,可以使用 shell 命令“ls
ai”验证这两个特殊文件的用法。
• 工作目录:每个进程都有一个当前工作目录(cwd, current working directory),用途为解释相对路
径。
2
APUE读书笔记
• 起始目录(用户家目录 home directory):用户登录后的初始目录,由文件/etc/passwd 指定
4、输入和输出
• 文件描述符(file descriptor):用以标识引用一个打开的文件,文件描述符是进程的属性。进程不同
值相同的文件描述符引用的可以是不同的文件。
• 标准输入、标准输出和标准出错:进程创建时自动打开的三个文件描述符,默认为 0、1、2,一般通
过用宏 STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO 来引用。
• 不带缓冲的 I/O:标准系统调用 open(2)、read(2)、write(2)、lseek(2)、close(2)不使用缓冲区,直接
把输入/输出送到内核,书中称为“不带缓冲的 I/O”。这里的缓冲位于进程地址空间;
• 标准 I/O:C 函数库中的标准 I/O 函数(定义在 stdio.h(7))使用缓冲区进行输入/输出、以提高吞
吐效率。编程时要注意 I/O 重定向及 fork(2)导致复制地址空间等情况下标准 I/O 函数对缓冲区的使用
情况。
5、程序与进程
• 程序是一个静态的概念,指存放在存储介质上可被内核通过 exec(3)系统调用读入并执行其中指令的
文件,可能是二进制也可能是文本形式。Unix 上的程序需要执行权限。
• 进程是执行中的程序,除了程序本身的代码文本、数据外,进程还包括其它自身拥有的资源,诸如进
程 id(PID)、打开的文件、地址空间、未决信号集、控制线程等。
6、程序线程
• 对一个用户进程,内核实际执行调度处理的是它的执行线程。一个进程可以拥有一个或多个执行线程,
对进程来说这些线程是并发执行的。进程内的多个线程共享进程资源。
7、异步、并发、通信
这几个术语也应该属于 Unix 系统较重要的基本概念的一部分。书中没有用专门的章节进行描述,这
里是一个补充。
• 异步(Asynchronous)指的是对系统资源以不可预测的时间和顺序执行的操作。例如等待外部输入、
监听 TCP 端口等都是异步操作。对于异步操作,需要设计阻塞等待或超时等机制(一般都是基于信
号机制实现)。
• 并发(Concurrency):多个并行的异步进程/线程同时在同一个资源上会合时,产生并发。这时由于
各自的异步性,读写等 I/O 操作可能交错发生乱序,从而出现意外的结果。为使它们的操作被强制的
顺序化,需要进行同步处理)。同步处理属于广义上的通信的范畴,有多种同步方式,一般采用锁机
制。同步处理还需要注意竞争条件出现的死锁。这是 Unix 系统编程中较为复杂、容易出现 bug 的地
方。
• 通信(Communication):指通过某种机制,在不同实体间交换数据,对 Unix 编程来说,发送/接收、
通知/响应、输入/输出等都属于比较广义的通信的范畴,狭义点的说法就指数据的发送/接收。Unix
编程的主要通信方式为进程间通信和线程通信。广义的进程间通信包括了信号、管道、IPC 对象、套
接字。条件变量、取消等操作可以用作线程间的通信(通知)。建议性锁和全局变量也是一种通信机
3
APUE读书笔记
制。不同应用场合的通信使用不同的机制和做法。
8、出错处理
•
Unix 系统一般通过设置全局变量 errno(3)标识程序执行时发生的错误。在系统所提供的库函数中,除
非再次发生错误,否则不会改动 errno 的值也不会将其清零。errno 可以通过下面两个函数转换为对应
的错误消息字符串。
#include
char *strerror(int errnum);
此函数将指定的 errno 错误号转换为字符串并返回这个字符串的指针;
#include
void perror(const char *msg);
此函数执行一个格式化输出,为指定的字符串+冒号+当前的 errno 值对应的字符串。相当于执行了:
printf ("%s: %s", msg, strerror(errno));
9、Unix 用户和用户标识
• 正常下,UID 唯一标识了一个用户;
• 系统的用户信息定义在/etc/passwd(passwd(5));
• 用户的创建、修改、删除通常由系统管理员通过 useradd(1)、userdel(1)、usermod(1)等系统命
令执行,而不应直接修改/etc/passwd 文件;
• 超级用户(root)的 UID 为 0;
• 组(group)将一个或多个用户组织起来,以使它们能以指定的相同权限访问资源;
• 正常下,GID 唯一标识了一个组;
•
• 组的创建、修改、删除通常由系统管理员通过 groupadd(1)、groupdel(1)、groupmod(1)等系统
GID 定义在/etc/group(group(5));
命令执行,而不应直接修改/etc/group 文件;
• 用户可以同时加入多个组,命令 groups(1)可以打印出用户所在的组,第一个以外的均为附加组;
10、信号
• 信号是软件中断机制,作为系统某种事件发生的通知;
• 进程可以通过调用信号函数,在信号递送到进程时选择对其的处理方式。对信号的处理有三种选择:
忽略(丢弃)、按系统的默认方式处理、使用自定义信号捕捉函数来处理;
• 进程还可以选择在信号递送之前屏蔽之,使之成为未决信号而延后处理;
• 进程捕捉到信号时将被中断,直到信号处理函数返回时方恢复执行;
4