这里的I/O指的是系统调用中的I/O,即不带缓存的I/O,函数申明如下
#include
int open(const char *path, int oflag, .../*mode_t mode*/);
成功,返回一个文件描述符,失败,返回-1
oflag可以选择:
O_RDONLY:只读
O_WRONLY:只写
O_RDWR:读写
O_APPEND:写最加到文件尾
O_CREATE:创建文件,需要使用第三个参数mode_t mode,表明文件的属性,如拥有者、权限等。
O_TRUNC:将文件长度设为0,即在下次写的时候将清除原来的内容
O_NONBLOCK:将读写操作设置为非阻塞,注意,只能对打开的文件类型为FIFO,块特殊文件,字符特殊文件有效,比如socket。
O_SYNC:同步写,即每次write时都等待物理I/O,包括对文件属性的写,如文件长度,修改时间等后返回。
一个常用用法:
open(path, O_CREATE|O_EXCL)是一个原子操作,如果path已经存在了,则失败,否则创建文件并成功返回。
#include
int create(const char *path, mode_t mode)
成功,返回一个文件描述符,失败,返回-1
等同于调用open(path, O_WRONLY|O_CREATE|O_TRUNC, mode)
#include
int close(int fd);
成功,返回0,失败,返回-1
进程终止时,内核将自动关闭进程打开的所有文件描述符。
#include
off_t lseek(int fd, off_t offset, int whence);
成功,返回新的文件偏移量,失败,返回-1
off_t的类型为int
whence有三个选择:SEEK_SET,SEEK_CUR,SEEK_END,分别对应文件起始位置,当前位置和文件尾。
#include
ssize_t read(int fd, void *buf, size_t nbytes);
成功,返回读入的字节数,如果已经到达文件尾,返回0,失败,返回-1
size_t的类型为unsigned int
ssize_t的类型为int,即带符号的size_t
#include
ssize_t write(int fd, void *buf, size_t nbytes);
成功,返回写入的字节数,失败,返回-1
打开文件时的内核数据结构如下图所示,注意,在linux中v节点其实也是一种i节点:
有了上图,就可以很容易的理解dup(2)和dup2(2)系统调用了:
#include
int dup(int fd)
int dup2(int fd, int fd2)
上面两个函数在成功时返回新的文件描述符,失败是返回-1。
需要注意的是,dup返回的是当前未使用的最小的fd值,dup2先关闭fd2,然后返回fd2。
从图中来看,dup(2)和dup2(2)都是将返回的fd的文件表指针指向原fd的文件表。
一些同步的函数:
#include
int fsync(int fd);
int fdatasync(int fd);
int sync(void);
上面三个函数成功时返回0,失败时返回-1。
sync函数将所有修改过的内核缓冲区排入写队列,然后返回,并没有等待实际的磁盘写操作。
fync将指定文件描述符相关的修改过的内核缓冲区排入写队列并等待物理I/O完成后返回。
fdatasync函数与fsync不同的地方在于fsync除了文件数据,还有文件属性信息的物理I/O,而fdatasync只有文件数据的物理I/O。
#include
int fcntl(int fd, int cmd, .../*mode_t mode*/);
成功后返回值依赖于cmd,失败返回-1。
fcntl函数的五种功能:
- 复制文件描述符,cmd=F_DUPFD
- 获得/设置文件描述符标志,cmd=F_GETFD或F_SETFD。当前只有一种文件描述符标志,即FD_CLOEXEC,即在调用exec系统调用时是否关闭文件描述符。
- 获得/设置文件状态,文件状态即open函数中的oflag参数。
- 获得/设置异步I/O所有权。
- 获得/设置记录锁。
阅读(507) | 评论(0) | 转发(0) |