UNIX中的文件 I/O

文件描述符

对于内核而言,所有打开的文件都通过文件描述符引用。文件描述符是一个非负整数。当打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。

函数 open 和 openat

调用 open 或 openat 函数可以打开或创建一个文件。

#include <fcntl.h>

int open(const char *path, int oflag, ...);

int openat(int fd, const char *path, int oflag, ...);

两函数的返回值:若成功,返回文件描述符;若出错,返回-1

... 表示余下的参数的数量及其类型时可变的。

path 参数时要打开或创建文件的名字。oflag 参数可用来说明此函数的多个选项,用下列一个或多个常量进行“或”运算构成oflag参数。

O_RDONLY         只读打开

O_WRONLY        只写打开

O_RDWR             读、写打开

O_EXEC              只执行打开

O_SEARCH        只搜索打开(应用于目录)

在这五个常量中必须指定一个且只能指定一个。下列常量则是可选的。

O_APPEND        每次写时都追加到文件的尾端。

O_CLOEXEC        把FD_CLOEXEC 常量设置为文件描述符标注。

O_CREAT           若此文件不存在则创建它。使用此选项时,open 函数需同时说明第三个参数 mode,用 mode 指定该新文件的访问权限位。

O_DIRECTORT        如果 path 引用的不是目录,则出错。

O_EXCL            如果同时指定了 O_CREAT ,而文件已经存在,则出错。

O_NOCTTY         如果 path 引用的是终端设备,则不将该设备分配作为此进程的控制终端。

O_NOFOLLOW        如果 path 引用的是一个符号链接,则出错。

O_NONBLOCK        如果 path 引用的是一个 FIFO、一个块特殊文件或一个字符特殊文件,则此选项为文件的本次打开操作和后续的 I/O 操作设置非阻塞方式。

O_SYNC             使每次 write 等待物理 I/O 操作完成,包括由该 write 操作引起的文件属性更新所需的 I/O。

O_TRUNC         如果此文件存在,而且只写或读-写成功打开,则将其长度截断为0。

O_TTY_INIT          如果打开一个还未打开的终端设备,设置非标准 termios 参数值。

下面两个标志也是可选的,它们是POSIX.1 中同步输入和输出选项的一部分。

O_DSYNC         使每次 write 要等待物理 I/O 操作完成,但是如果该写操作并不影响读取刚写入的数据,则不需等待文件属性被更新。

O_RRSYNC         使每一个以文件描述符作为参数进行的 read 操作等待,直至所有对文件同一部分挂起的写操作都完成。

由 open 和 openat 函数返回的文件描述符一定是最小的未用描述符数值。

fd参数把 open 和 openat 函数区分开,共有3中可能性:

1. path 参数指定的是绝对路径名,在这种情况下,fd参数被忽略,openat 函数就相当于 open 函数。

2. path 参数指定的是相对路径名,fd参数指出了相对路径名在文件系统中的开始地址。fd参数是通过打开相对路径名所在的目录来获取。

3. path 参数指定了相对路径名,fd参数具有特殊值 AT_FDCWD。在这种情况下,路径名在当前工作目录中获取,openat 函数在操作上与open函数相似。

函数creat

可用调用 creat 函数创建有一个新文件:

#include <fcntl.h>

int creat(const char *path, mode_t mode);

返回值:若成功,返回为只读打开的文件描述符;若出错,返回-1

函数close

调用close函数关闭一个打开文件

#include <unistd.h>

int close(int fd);

返回值:若成功,返回0;若出错,返回-1

关闭一个文件时还会释放该进程加在该文件上的所有记录锁。

当一个进程终止时,内核自动关闭它所有的打开文件。

函数lseek

调用 lseek 显示地为一个打开的文件设置偏移量

#include <unistd.h>

off_t lseek(int fd, off_t offset, int whence);

返回值:若成功,返回新的文件偏移量;若出错,返回-1.

对参数 offset 的解释与参数 whence 的值有关:

1. 若 whence 是 SEENK_SET,则将该文件的偏移量设置为距文件开始处offset个字节。

2. 若whence 是 SEEK_END,则将该文件的偏移量设置为文件长度加 offset,offset 可正可负。

3. 若whence 是 SEEK_CUR,则将该文件的偏移量设置为其当前值加 offset,offset 可正或负。

函数 read

调用 read 函数从打开文件中读数据

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t nbytes);

返回值:读到的字节数,若已到文件尾,返回0;若出错,返回-1

有多种情况可使实际读到的字节数少于要求读的字节数:

1. 读普通文件时,在读到要求字节数之前已到达了文件尾端。

2. 当从终端设备读时,通常一次最多读一行。

3. 当从网络读时,网络中的缓冲机制可能造成返回值小于所要求读的字节数。

4. 当从管道或FIFO读时,如若管道包含的字节少于所需的数量,那么 read 将只返回实际可用的字节数。

5. 当从某些面向记录的设备(如磁带)读时,一次最多返回一个记录。

6. 当一信号造成中断,而已经读了部分数据量时。

注:读操作从文件的当前偏移量处开始,在成功返回之前,该偏移量将增加实际读到的字节数。

函数write

调用 write 函数向打开文件写数据

#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t nbytes);

返回值:若成功,返回已写的字节数;若出错,返回-1

其返回值通常与参数 nbytes 值相同,否则表示出错。write 出错的一个常见原因时磁盘已写满,或者超过一个给定进程的文件长度限制。

对于普通文件,写操作从文件的当前偏移量处开始。如果在打开该文件时,指定了 O_APPEND 选项,则在每次写操作之前,将文件偏移量设置在文件的当前结尾处。在一次成功写入之后,该文件偏移量增加实际写的字节数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值