以前在课堂上学习过《Unix初级教程(第四版)》,对于Unix有了一点了解。由于以后使用的需要,要对它进行比较深入的学习,为此需要阅读不少的书籍,这本《Unix环境高级编程》便在此列。希望能通过这本书了解Linux的API,并在这个过程中了解Linux系统的机制。书中内容丰富,有以前了解的,更多的是不了解的。作为第一次阅读,目的不在于事无巨细,过目不忘,而是有个大体了解,从点到面地熟悉这个系统。为了构建整体的印象,对已知的和刚刚了解的都有所涉及。同时作为笔记,不希望成为对目录的简单复制,而是能成为对学习的程度和体会的记录。
第一章 基础知识
这一章本身就是概括,略。
旧知:
体系结构、登录、shell简介
第二章 UNIX标准化及实现
旧知:
ISO C、POSIX、系统实现(SVR4、4.4BSD、FreeBSD、Linux、Mac OS X、Solaris)
新知:
Single UNIX Specification(POSIX.1的一个超集)、各个标准作出的限制(sysconf、pathconf、fpathconf可以获得)
第三章 文件I/O
旧知:
文件描述符、文件I/O函数(open、creat、close、lseek、read、write以及可能造成的文件空洞)、I/O效率(缓冲区大小)、
打开文件使用的数据结构(进程表项、文件表、v节点表)、原子操作
新知:
文件描述符的复制(dup和dup2)、及时手动更新缓冲区(sync、fsync、fdatasync)、获取和设置已打开的文件的性质(fcntl)
另外从这一章起,逐渐发现和文件操作有关的同一种功能的函数经常有两个版本,前面带f的参数一般是文件描述符filedes,不带f的使用路径pathname。
第四章 文件和目录
旧知:
文件类型、用户ID和组ID、文件访问权限、权限的修改(chmod、fchmod)、文件长度(不含空洞情况)、基本操作(remove、rename、mkdir、rmdir)
新知:
查看文件属性(stat、fstat、lstat)、目录的读权限和执行权限、权限测试(access)、权限屏蔽字的设置(umask)、粘住位(如果支持,在交换区保护正文)、
更改用户ID和组ID(chown、fchown、lchown)、文件截短、文件系统(i节点、数据块和目录块、目录文件和普通文件的不同)、
硬链接(在原有知识之上,link、unlink的使用和具体操作、临时文件的删除)、符号链接(symlink、readlink、构成循环的符号链接)、文件时间的修改(utime)
工作目录及更改(chdir、fchdir、getcwd)、设备特殊文件(st_dev和st_rdev的区别)
第五章 标准I/O库
类似于涉及文件操作的一些函数,流操作的一些函数的也有三个版本:前缀s的把字符写入缓冲区buf,前缀f的写入指定流,不带前缀的写入到标准输入输出。这只是一个概括。
旧知:
流和FILE对象、标准输入、标准输出、标准出错、流的打开(fopen、freopen、fdopen)
字符读(getc、fgetc、getchar和相关的ferror、feof、clearerr、ungetc)和写(putc、fputc、putchar)
按行I/O(fgets、gets、fputs、puts)
格式化I/O(printf、fprintf、sprintf、snprintf、scanf、fscanf、sscanf和一些其他变体)
新知:
标准I/O效率、二进制I/O(一次处理整个结构fread、fwrite)、定位流(ftell、fseek、rewind、ftello、fseeko)
临时文件(创建和维护:tmpnam、tmpfile)
标准I/O库实际并不完善,这和基本设计和不同的实现有关。不足之处之一是效率不高,软件包是一个代替方法。
第六章 系统数据文件和信息
旧知:
口令文件
新知:
阴影口令、组文件、附加组ID、登录账户记录、时间日期函数
第七章 进程环境
旧知:
exit函数(exit、_exit和_Exit)、C程序存储空间布局、存储器分配(malloc、calloc、realloc)、环境变量、跨函数跳转(setjmp和longjmp)
新知:
atexit函数、环境表、共享库(库函数的动态链接,减小可执行文件长度)、进程资源限制(getrlimit和setrlimit函数)
第八章 进程控制
旧知:
进程标识符、fork()、exit()、wait()和waitpid()、竞争条件、exec()、
新知:
vfork()、waitid()、wait3和wait4、exec的六种形式和工作过程、更改用户ID和组ID、解释器文件(执行其第一行所指定的文件)、system()、
进程会计(产生进程的各项运行记录)、用户标识、进程时间(不是很理解墙上时钟时间)
对于程序清单8-9中使用的变量environ可以参考:http://topic.csdn.net/t/20060820/13/4962381.html
第九章 进程关系
新知:
终端登录过程、getty程序、进程组、会话、控制终端(与会话和进程组相关)、与前面三项相关联的tcgetpgrp、tcsetpgrp、tcgetsid
作业控制(中断、退出、挂起;后台运行和转为前台)、孤儿进程组
一个作业只是几个进程的集合,通常是一个进程的管道线。对于这章内容,之前只知道如何让程序后台运行(加&)和查看,其他方面了解的很少。
9.9节shell执行程序想说明在不同版本的UNIX上shell执行程序的方式以及这和上面一些概念的关系,感觉自己的理解还是不到位。
第十章 信号
旧知:
signal()(告诉内核出现某个信号时应采取的操作)
新知:
可重入函数、一些信号语义、kill()和raise()、alarm()和pause()
信号集和相关操作(sigemptyset、sigfillset、sigaddset、sigdelset、sigismember、sigprocmsak、sigpending、sigaction)
sigsetjmp()和siglongjmp()、sigsuspend()、abort()与system()和sleep()在信号情景下的实现、作业控制信号
对于信号,以往了解的比较少,这部分的阅读时间拖得也比较长,了解仍不够深入。目前只是对信号机制的作用方式有所了解,但读后感觉确实对于理解UNIX里的一些其它机制的实现有了不同的认识。
第十一章 线程
旧知:
线程标识tid、线程创建pthread_create()、线程终止pthread_exit()和相关的pthread_join()、线程同步之互斥量mutex
新知:
对同一个互斥量加锁两次会造成死锁(以前只知道两个线程循环请求的死锁);条件变量作为同步机制的应用
第十二章 线程管理
新知:
线程属性(分离状态、警戒缓冲区、线程栈低地址和大小、取消)、线程的同步对象属性(互斥量、读写锁)、线程级的函数重入、线程私有数据
线程和信号(由同一个进程共享)、线程与fork和I/O
第十三章 守护进程
新知:
常见守护进程、创建守护进程、出错日志
本章内容也是第一次了解,由于涉及信号处理,对于示例仍处于一知半解的状态。
第十四章 高级I/O
新知:
非阻塞I/O、记录锁、STREAMS、I/O多路转接的实现(select()、pselect()、poll())、异步I/O(涉及不同系统)
readv和writev()、readn()和writen()、存储映射I/O:mmap()
对于记录锁,以往知道一些,这里做了进一步了解。
STREAMS只是大概了解了其功能和普通的流的差异,多路转接也是只做了简单了解。
关于mmap、readn()、writen()与传统的read()&write()的性能差异书中亦有分析。
第十五章 进程间通信
进程间通信即IPC,对于这章提到的管道、FIFO、消息队列、信号量和共享存储,以前有所了解。这章细节内容比较多,暂且根据目前的理解总结一下。
管道只限于具有公共祖先的进程之间使用,使用方式:初始化管道->关闭不用的读或写端->数据传送。由管道的特性和使用方式,有相关的函数popen()和pclose()。协同进程的例子试了一试,加深了理解。
FIFO是一种文件类型,文件I/O函数自然可以用于操作FIFO。
除了管道和FIFO,后三种都属于XSI IPC,它们的相似处在于其IPC结构(标识符ID和键key、权限结构、结构限制),在系统范围内使用。它们的操作函数的格式比较类似:由key获得ID的msgget()、semget()、shmget();操作函数msgctl()、semctl()、shmctl()。消息队列和信号量还各有自己的特有结构:前者是消息,后者是信号量集和信号量。消息队列特有的操作:消息入队msgsnd()和出队msgrcv();信号量特有操作semop();共享存储特有操作:连接到地址空间shmat()、地址空间脱离shmdt()。
书中信号量部分似乎漏了一行:信号量集是如何提供它所包含的信号量的入口的。在书中struct semid_ds中遗漏的一行如下:
struct sem *sem_base /*指向集合中第一个信号量的地址*/
参考了APUE的电子版(似乎是第一版)和这个帖子:http://bbs.chinaunix.net/thread-483853-1-1.html才有了上面的结论。个人认为如果是有意省略,确实不恰当。
第十六章 网络IPC:套接字
对于套接字之前通过《TCP/IP Sockets编程(C语言实现) 》有所学习,这章对于作者来说是个复习。地址族、字节序、通用地址结构sockaddr、套接字地址sockaddr_in和一些相应的转换函数不必再提;查询配置信息的函数gethostent()、getnetent()、getprotoent()、getservent()和一些相关函数是第一次遇到,或许是因为它们是BSD网络软件提供的接口,简单的了解了一下。getaddrinfo()和getnameinfo()比较熟悉,也不细述。
对于一些和套接字操作相关的函数,根据阅读和对程序清单的理解,大体使用方式简述为如下,
客户机,创建并填充socket后,面向连接的需要先connect()后send()或recv();无连接不用connnect()而是直接使用sendto()和recvfrom()。sendmsg()和recvmsg()用于使用多重缓冲区进行消息传送,其参数不涉及destaddr,应该是面向连接的。
服务器,创建并填充socket,先bind(),打开listen()。面向连接需要在收到请求后使用新的socket进行accept(),原socket继续侦听;无连接侦听到后即可使用原socket进行数据传输。使用函数和客户机一样,按是否面向连接选用。
带外数据是一些通信协议所支持的可选特征。TCP仅支持一个字节的紧急数据,在普通数据传递机制数据流之外传输。这里涉及到信号发送和处理。
recv()和send()涉及到非阻塞和异步I/O,其又与信号有关,行为和阻塞模式下不同,使用方法介绍的比较简单,不在此赘述。
第十七章 高级进程间通信
本章主要介绍的是基于STREAMS的管道和域套接字这两种进程间通信方式,后面的实例即是对它们的使用。理解的还不够,目前还是一知半解的状态。
第十八至二十一章
这四章分别介绍终端I/O、伪终端、数据库函数库、与网络打印机通信,前两者以前完全没接触过,现在仅仅了解基本概念;后两者是具体实现,源代码也没有研读。
花了近两个月终于算是把这本书大体浏览了一遍,更加感到不了解的东西还很多,需要学习的东西还很多。