文件I/O(系统调用API)
文件描述符
概念
文件描述符是一个非负整数,对于内核而言所有打开的文件都通过文件描述符引用。
在Unix系统shell进程中:
fd:0 STDIN_FILENO 与标准输入相关联
fd:1 STDOUT_FILENO 与标准输出相关联
fd:2 STDERR_FILENO 与标准错误相关联
数据结构
每一个打开的文件,内核使用打开文件描述符表,文件表项 以及 v节点表项(Linux中的i节点) 三种数据结构来表示
- 打开文件描述表
每个进程的PCB(进程控制块)中都包含一个该表的指针;
在打开文件描述符表中,每个文件描述符占用该表的一项
每个文件描述表项由 文件描述符标志 和 指向一个文件表项的指针构成
- 文件表
内核为所有打开文件维持一张文件表,每个文件表项包括:
a. 文件状态标志
b. 当前文件偏移量
c. 指向该文件的v节点表现的指针
- v节点
每个打开文件都有一个v节点。
v节点对象由文件类型和对此文件进行各种操作的方法构成
读写相关的I/O
创建文件功能的I/O
int open(const char *path, int flag, ... /* mode_t mode*/)
int open(int fd, const char *path, int flag, ... /* mode_t mode*/)
int creat(const char *path, mode_t mode)
上述I/O具有创建文件的功能,创建成功返回文件描述符,失败返回-1
读写文件功能的I/O
ssize_t read(int fd, void *buf, size_t nbytes)
ssize_t write(int fd, const void *buf, size_t nbytes)
off_t lseek(int fd, off_t offset, int whence)
read: 读取成功则返回读取的字节数,若到达尾端则返回0
普通文件:若读取要求字节数前已到达尾端,则返回所读取的字节数
特殊文件:
- 终端设备:通常一次最多读取一行
- 管道或者FIFO:read只读取到实际可用的字节数
- 网络:读取缓冲区中的字节数
- 面向记录的设备:一次只返回一个记录
write: 返回值通常与参数nbytes相同,否则出错
lseek: 可以设置文件偏移量
按照系统默认,当打开一个文件时,若未指定O_APPEND属性,则文件偏移量设置为0
whence参数可取,SEEK_SET, SEEK_CUR, SEEK_END
SEEK_SET: 该文件的偏移量设置为距文件开始处offset处
SEET_CUR: 该文件的偏移量设置为当前位置加上offset处,此时offset可正可负
SEET_END: 该文件的偏移量设置为文件的长度加上offset处,offset可正可负
其他功能性I/O
冲刷内核缓冲区I/O
int fsync(int fd)
int fdatasync(int fd)
void sync(void)
复制文件描述符I/O
int dup(int fd)
int dup(int fd, int fd2)
int fcntl(int fd, int cmd, ... /* int arg**/)
int ioctl(int fd, int request, ...)
/dev/fd/n