Direct I/O
为open()提供ODirect标志可以指示内核将I/O管理的存在降到最低。当提供此标志时,I/O将直接从用户空间缓冲区启动到设备。 传递页面缓存。所有的I/O都是同步的;操作直到完成才会返回。
在执行直接I/O时,请求长度、缓冲区对齐和文件偏移量都必须是基础设备扇区大小的整数倍数-通常为512字节。
Closing Files
#include <unistd.h>
int close(int fd);
if(close(fd) == -1)
perror("close")
关闭文件与文件刷新到硬盘上无关。
要确保在关闭文件之前将文件提交到磁盘,应用程序需要使用一个同步选项。
如果文件已从磁盘断开链接,但在未链接之前一直处于打开状态,则在关闭文件和从内存中删除其inode之前,不会实际删除该文件。因此,调用close()还会导致一个未链接的文件最终被物理地从磁盘中删除。
Error Values
不检查close()的返回值是一个常见错误。
虽然POSIX允许这样做,但close()永远不会返回EINTR。Linux内核开发人员知道得更清楚。
Seeking with lseek()
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t pos, int origin);
lseek()的行为取决于origin参数,它可以是以下内容之一:
- SEEK_CUR
fd的当前文件位置被设置为它的当前值加上pos,它可以是负的、零的,也可以是正的。0的pos返回当前文件位置值。 - SEEK_END
fd的当前文件位置被设置为文件的当前长度加上pos,它可以是负的、零的,也可以是正的。0的pos将偏移量设置为文件的末尾。 - SEEK_SET
fd的当前文件位置设置为pos。0的pos将偏移量设置为文件的开头。
调用在成功时返回新的文件位置。如果出现错误,则返回−1,并酌情设置errno。
off_t ret;
ret = lseek(fd, (off_t)1825, SEEK_SET);
if(ret == (off_t)-1)
/* error */
off_t ret;
ret = lseek(fd, 0, SEEK_END);
if(ret == (off_t) -1)
/* error */
int pos;
pos = lseek(fd, 0, SEEK_CUR);
if(pos == (off_t) -1)
/* error */
else
/* 'pos' is the current position of fd */
Seeking Past the End of a File
int ret;
ret = lseek(fd, (off_t)1688, SEEK_END);
if(ret == (off_t)-1)
/* error */
可以指示lseek()将文件指针移过文件结尾。
对新创建的文件位置的读取请求将返回EOF。
如果随后进行写请求,新的空间将在文件的旧长度和新长度之间创建,并将用零填充。
这个零填充物叫做a hold。
在Unix风格的文件系统上,holes不占用任何物理磁盘空间.这意味着一个文件系统上所有文件的总大小可以超过磁盘的物理大小。带有holes的文件称为spare files。spare files可以节省相当大的空间并提高性能,因为操作holes不会启动任何物理I/O。对在holes中对文件的部分进行读取将返回适当数量的零。
Error Values
出错时,lseek()返回−1,错误号设置为以下四个值之一:
- EBADF
给定的文件描述符和打开的文件描述符无关。 - EINVAL
指定的origin是不是SEEK_SET、SEED_CUR或SEED_END中的其中一个,或是产生的文件位置为负值。 - EOVERFLOW 产生的文件偏移量不能用OFF_t表示。这只能发生在32位架构上。当前,文件位置被更新;此错误仅表示不可能返回它。
- ESPIPE
给定的文件描述符是不可查找的对象,例如 pipe、FIFO或socket。
网友评论