unix系统中的大多数文件I/O只需用到5个函数:open、read、write、lseek、close。
术语不带缓冲指的是每个read和write都调用内核中的一个系统调用。
只要涉及在多个进程间共享资源,原子操作将会变得非常重要。
由open返回的描述符一定是最小的未用的描述符值。
int open(char* filename, int oflag, .../*mode*/);
我们将第三个参数写为...,ISO C用这种方法表明余下的数量及其类型根据具体的调用会有所不同。
oflag常用参数
以下三个必须指定一个并且只能指定一个。
O_RDONLY 只读
O_WRONLY 只写
O_RDWR 读写
以下为可选
O_APPEND 每次写时都追加到文件尾端
O_CREATE 若文件不存在,则创建它。使用该选项时,需要第三个参数mode,用其指定新文件的权限访问位。
O_EXCL 如果同时制定O_CREAT,而文件存在,则会出错。用此可以测试一个文件是否存在,如果不存在,则创建此文件,这使创建和测试两者称为一个原子操作。
O_TRUNC 如果此文件存在,并且以只写或者读写成功打开后,将其长度截断为0。
更多选项可通过man 2 read查看。
int close(int fd);
1、关闭一个文件时,还会释放该进程加在该文件上的所有记录锁。
2、当一个进程终止时,它所有打开的文件都会被内核关闭。
每个打开的文件都有一个与其相关联的“当前文件偏移量”,它通常是一个非负整数,用以度量从文件开始处的字节数量。通常,读、写操作都从当前文件偏移量处开始,并使偏移量增加所读写的字节数。按系统默认的情况,当打开一个文件时,除非指定O_APPEND选项,否则该偏移量被设置为0。
off_t lseek(int fd, off_t offset, int whence);
若whence是SEEK_SET,则将该文件的偏移量设置为距文件开始处offset个字节。
若whence是SEEK_CUR,则将该文件的偏移量设置为当前值加offset,offset可为正或负。
若whence是SEEK_END,则将该文件的便宜两设置为文件长度加offset,offset可以为正或负。
若lseek成功执行,则返回新的文件偏移量,为此可以用下列方法确定打开文件的当前偏移量:
off_t currpos;
currpos = lseek(fd, 0, SEEK_CUR);
这种方法可以用来确定所涉及的文件是否可以设置偏移量。如果文件描述符引用的是一个管道、FIFO或网络套接字,则lseek返回-1,并将errno设置为ESPIPE。
lseek仅将当前的文件偏移量记录在内核中,它并不引起任何I/O操作。然后,该偏移量用于下一个读或写操作。
文件偏移量可以大于文件的当前长度,在这种情况下,对文件的下一次写将加长该文件,并在文件中构成一个空洞,这一点是被允许的。位于文件中但没有写过的字节都被读为0。
文件中的空洞并不要求在磁盘上占用存储区。具体实现方法和文件系统的实现有关,当定位到超出文件尾端之后写时,对于新写的数据需要分配磁盘块,但是对原文件味道和新开始写位置之间的部分则不需要分配磁盘块。
术语不带缓冲指的是每个read和write都调用内核中的一个系统调用。
只要涉及在多个进程间共享资源,原子操作将会变得非常重要。
由open返回的描述符一定是最小的未用的描述符值。
int open(char* filename, int oflag, .../*mode*/);
我们将第三个参数写为...,ISO C用这种方法表明余下的数量及其类型根据具体的调用会有所不同。
oflag常用参数
以下三个必须指定一个并且只能指定一个。
O_RDONLY 只读
O_WRONLY 只写
O_RDWR 读写
以下为可选
O_APPEND 每次写时都追加到文件尾端
O_CREATE 若文件不存在,则创建它。使用该选项时,需要第三个参数mode,用其指定新文件的权限访问位。
O_EXCL 如果同时制定O_CREAT,而文件存在,则会出错。用此可以测试一个文件是否存在,如果不存在,则创建此文件,这使创建和测试两者称为一个原子操作。
O_TRUNC 如果此文件存在,并且以只写或者读写成功打开后,将其长度截断为0。
更多选项可通过man 2 read查看。
int close(int fd);
1、关闭一个文件时,还会释放该进程加在该文件上的所有记录锁。
2、当一个进程终止时,它所有打开的文件都会被内核关闭。
每个打开的文件都有一个与其相关联的“当前文件偏移量”,它通常是一个非负整数,用以度量从文件开始处的字节数量。通常,读、写操作都从当前文件偏移量处开始,并使偏移量增加所读写的字节数。按系统默认的情况,当打开一个文件时,除非指定O_APPEND选项,否则该偏移量被设置为0。
off_t lseek(int fd, off_t offset, int whence);
若whence是SEEK_SET,则将该文件的偏移量设置为距文件开始处offset个字节。
若whence是SEEK_CUR,则将该文件的偏移量设置为当前值加offset,offset可为正或负。
若whence是SEEK_END,则将该文件的便宜两设置为文件长度加offset,offset可以为正或负。
若lseek成功执行,则返回新的文件偏移量,为此可以用下列方法确定打开文件的当前偏移量:
off_t currpos;
currpos = lseek(fd, 0, SEEK_CUR);
这种方法可以用来确定所涉及的文件是否可以设置偏移量。如果文件描述符引用的是一个管道、FIFO或网络套接字,则lseek返回-1,并将errno设置为ESPIPE。
lseek仅将当前的文件偏移量记录在内核中,它并不引起任何I/O操作。然后,该偏移量用于下一个读或写操作。
文件偏移量可以大于文件的当前长度,在这种情况下,对文件的下一次写将加长该文件,并在文件中构成一个空洞,这一点是被允许的。位于文件中但没有写过的字节都被读为0。
文件中的空洞并不要求在磁盘上占用存储区。具体实现方法和文件系统的实现有关,当定位到超出文件尾端之后写时,对于新写的数据需要分配磁盘块,但是对原文件味道和新开始写位置之间的部分则不需要分配磁盘块。