《Unix系统编程手册》第四章 通用的I/O模型

2 篇文章 0 订阅

打开文件:open()

open既能打开一个已存在的文件,也可以创造一个新文件。当调用open()创建新文件时,位掩码参数mode指定了文件的访问权限。如果open()未指定O_CREAT标志,则可以省略mode参数。

#include <sys/stat.h>
#include <fcntl.h>

int open(const char* pathname, int flags, ... /* mode_t mode*/);
// return file descriptor on success, or -1 on error
/*
*pathname	:路径名,如果是符号链接,会对其进行解引用
*flags		:位掩码,用于指定	文件的访问模式
*return		:成功返回文件描述符,失败则返回-1
*/

文件访问模式:

访问模式描述
O_RDONLY以只读方式打开文件
O_WRONLY以只写方式打开文件
O_RDWR以读写方式打开文件

flag参数除了使用文件访问标志外,还用了其他操作标志。其他open系统调用的flags参数值:

标志用途
O_CLOEXEC设置close-no-exec标志
O_CREAT如果文件不存在,则创建文件
O_DIRECT无缓冲的输入/输出
O_DIRECTORY如果pathname不是目录,则失败
O_EXCL结合O_CREAT使用,专门用于创建文件
O_LARGEFILE在32位系统中使用此标志 打开大文件
O_NOATIME调用read()时,不修改文件最近访问时间
O_NOCTTY不要让pathname成为控制终端
O_NOFOLLOW对符号链接不予解引用
O_TRUNC截断已有文件,使其长度为零
O_APPEND总在文件尾部追加数据
O_ASYNC当I/O操作可行时,产生信号通知进程
O_DSYNC提供同步的I/O数据完整性
O_NONBLOCK以非阻塞方式打开
O_SYNC以同步方式写入文件

通过fcntl()的F_GETFL操作可以获取到文件的访问模式。

open文件出错

在打开文件出现错误时,open()函数调用将会返回-1,并通过设置错误号errno来标识错误原因。可能的错误号有:

  • EACCES:文件权限不允许调用进程以flags参数指定的方式打开文件,可能是访问权限不够或者文件不存在等
  • EISDIR:所指定的文件为目录,而调用者企图对目录写入
  • EMFILE:进程所打开的文件描述符数量达到了进程资源限制的上限
  • ENFILE:文件打开数量达到了系统允许的上限
  • ENOENT:文件不存在且未指定O_CREAT标志,或者pathname所指定的路径有问题
  • EROFS:文件只读,无法以只写或者读写的方式打开
  • ETXTBSY:文件为可执行程序,且正在执行

读取文件内容:read()

read()系统调用从文件描述符fd所指代的打开文件中读取数据

#include<unistd.h>
ssize_t read(int fd, void *buffer, size_t count);

count参数指定最多能读取的字节数,buffer参数提供用来存放输入数据的内存缓冲区地址,且缓冲区至少应有count个字节。
如果read()调用成功,将会返回实际读取的字节数,如果遇到文件结束(EOF)则返回0,如果出现错误则返回-1。

数据写入文件:write()

write()系统调用将数据写入一个已打开的文件中。

#include<unistd.h>
ssize_t write(int fd, void* buffer, size_t count);
//return number of bytes written or -1 on error

buffer参数为要写入文件中数据的内存地址,count参数为想要从buffer写入文件的数据字节数,fd参数为文件描述符,指代数据要写入的文件。
对磁盘文件执行I/O操作时,write()调用成功并不能保证数据已写入磁盘。这是因为减少磁盘活动量和加快write()系统调用,内核会缓存磁盘的I/O操作。

关闭操作:close()

close()系统调用会关闭一个打开的文件描述符,并将其释放回调用进程,供进程继续使用。当一个进程终止时,会自动关闭已打开的所有文件描述符。

#include<unistd.h>
int close(int fd);
//return 0 on success or -1 on error

改变文件偏移量:lseek()

对于每个打开的文件,系统内核会记录其文件偏移量。文件偏移量是指执行下一个read()或write()操作的文件起始位置,会以相对于文件头部起始点的文件当前位置来表示。文件第一个字节的偏移量为0。

文件打开时,会将文件偏移量设置为指向文件开始,以后每次read()和write()调用将按顺序递进,对文件进行操作

针对文件描述符fd参数所指代的已打开文件,lseek() 系统调用按照offset和whence参数值调整该文件的偏移量。

#include<unistd.h>
off_t lseek(int fd, off_t offset, int 	whence);
//return new file offset if successful or -1 on error

offset参数指定了一个以字节为单位的数值。whence参数则表明应参照哪个基点来解释offset参数,主要有以下几个:
SEEK_SET:将文件偏移量设置为从文件头部起始点开始的offset个字节
SEEK_CUR:相对于当前文件偏移量,将文件偏移量调整offset个字节
SEEK_END:将文件偏移量设置为起始于文件尾部的offset个字节

lseek()并不适用于所有类型的文件,不允许将lseek()应用于管道、FIFO、socket或者终端。

文件空洞

从文件结尾后到新写入数据间的这段空间被称为文件空洞。从编程角度看,文件空洞中是存在字节的,读取空洞将返回0填充的缓冲区。

然而,文件空洞不占用任何磁盘空间。直到后续某个时点,在文件空洞中写入了数据,文件系统才会为之分配磁盘块。其优势在于与实际分配的空字节分配磁盘块相比,稀疏填充的文件会占用较少的磁盘空间。

通用I/O模型以外的操作:ioctl()

ioctl()系统调用为执行文件和设备操作提供了一种多用途机制。

#include<sys/ioctl.h>
int ioctl(int fd, int request, ... /*argp*/);
//Value returned on success depends on request, or -1 or error

fd参数为某个设备或已打开的文件描述符,request参数指定了将在fd上执行的控制操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值