《UNIX环境高级编程》学习笔记,《UNIX环境高级编程》学习记录

时间:2021-06-25 14:42 作者:IIS7 admin

    以前在课堂上学习过《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、伪终端、数据库函数库、与网络打印机通信,前两者以前完全没接触过,现在仅仅了解基本概念;后两者是具体实现,源代码也没有研读。
    花了近两个月终于算是把这本书大体浏览了一遍,更加感到不了解的东西还很多,需要学习的东西还很多。