大概四年前陆陆续续读过 APUE,那个时候还是第二版,并且那个时候对于很多概念没有什么清楚的认识,读起来很快就给忘了。 时光荏苒,四年很快过去了,我已经从当时刚转专业的大二学生,变成了正在读 CS 的研一学生。最近突然发现,原来我对 Unix 系统以及网络的协议栈感兴趣。趁着现在还在上学,搞来了一本第三版打算系统学起来。经过这几年的沉淀,对于书中讲述的很多问题不再是比较陌生,或者是读完了没什么感觉。感触最深的就是多线程和多进程部分,当时对于这些知识在生活中或者在现成的技术中是如何的应用还没什么概念,所以看的时候可能也没有用心。现在对于它们有了全新的理解,所以重新看一遍觉得确实受益匪浅。
不过,看书不能从中间取一段看,知识都是环环相扣的,特别是 APUE 这种经典,只能从头开始看。于是将我觉得重要的内容记录下来,留作以后查阅。
以上 5 个常量中必须制定一个且只能指定一个。还有一些常量是可选的,这里不赘述。
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
// 返回值:若成功,返回新的文件偏移量;若出错,返回 -1
对参数 offset
的解释与参数 whence
的值有关 若 whence
是 SEEK_SET
,则将该文件的偏移量设置为距文件开始处 offset
个子节。 若 whence
是 SEEK_CUR
,则将该文件的偏移量设置为其当前值加 offset
,offset
可为正或负。 * 若 whence
是 SEEK_END
,则将该文件的偏移量设置为文件长度加 offset
,offset
可为正或负。
若 lseek
成功执行,则返回新的文件偏移量,为此可以用下列方式确定打开文件的当前偏移量:
off_t currpos = lseek(fd, 0, SEEK_CUR);
这种方法也可涌来确定所涉及的文件是否可以设置偏移量。如果文件描述符指向的是一个管道、FIFO 或网络套接字,则 lseek
返回 -1
,并将 errno
设置为 ESPIPE
。
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t nbytes);
// 返回值:读到的字节数,若已到文件尾,返回 0;若出错,返回 -1
由多种情况可使实际读到的字节数少于要求读到的字节数: 读普通文件时,在读到要求字节数之前已到达了文件尾端。 当从终端设备读时,通常一次最多读一行。 当从网络读时,网络中的缓冲机制可能造成返回值小于所要求读的字节数。 当从管道或 FIFO 读时,如若管道包含的字节少于所需的数量,那么 read
将只返回实际可用的字节数。 当从某些面向记录的设备(如磁带)读时,一次最多返回一个记录。 当一信号造成中断,而已经读了部分数据量时。
#include <unistd.h>
ssize_t pread(int fd, void *buf, size_t nbytes, off_t offset);
// 返回值:读到的字节数,若已到文件尾,返回 0;若出错,返回 -1
ssize_t pwrite(int fd, const void *buf, size_t nbytes, off_t offset);
// 返回值:若成功,返回已写的字节数;若出错,返回 -1
调用 pread
相当于调用 lseek
后调用 read
,但是 pread
又与这种顺序调用有下列重要区别: 调用 pread
时,无法中断其定位和操作。 不更新当前文件偏移。 调用 pwrite
相当于调用 lseek
后调用 write
,但也与它们有类似的区别。
#include <unistd.h>
int dup(int fd);
int dup2(int fd, int fd2);
// 返回值:若成功,返回新的文件描述符;若出错,返回 -1
由 dup
返回的新文件描述符一定是当前可用文件描述符中的最小数值。对于 dup2
,可以用 fd2
参数指定新描述符的值。如果 fd2
已经打开,则先将其关闭。如若 fd
等于 fd2
,则 dup2
返回 fd2
,而不关闭它。 这些函数返回的新文件描述符与参数 fd
共享同一个文件表项。