- 论坛徽章:
- 0
|
初学编程
请大家轻拍
Advanced Programming in Unix Environment
File I/O
Unix上绝大多数的文件I/O操作可由5个函数完成:open,read,write,lseek,close。与标准I/O函数相比,通常这些函数被称为无缓冲的I/O,无缓冲意味着每次read或write都会调用系统内核。原子性操作在多进程共享资源时尤为重要。此外,还有dup,fcntl,sync,fsync,ioctl等函数。
所有打开的文件都会被分配一个文件标识符,这个标志符是一个非负整数。调用open或creat函数返回文件标识符,该标志符被用作read或write的参数来识别该文件。通常约定0表示标准输入,1表示标准输出,2表示标准错误。
在posix标准下,通常用STDIN_FILENO,STDOUT_FILENO,STDERR_FILENO代替,这些常数保存在<unistd.h>头文件中。
open函数:int open(const char *pathname, int oflag, …);
oflags取值O_RDONLY,O_WRONLY,O_RDWR,仅要且必须指定其中一个。另外可选的有:
O_APPEND追加,O_CREAT若文件不存在则创建,O_EXCL若文件存在则报错,O_TRUNC写或者写读打开时清空文件,O_NOCTTY,O_NONBLOCK;
O_DSYNC写操作等待物理I/O结束,O_RSYNC读等待写操作结束,O_SYNC写等待物理I/O结束
关于O_DSYNC与O_SYNC的区别,O_SYNC文件数据与属性同步更新,而O_DSYNC在不影响读数据不等待属性更新。
creat函数:int creat(const char *pathname, mode_t mode);
等价于open(pathname, O_WRONLY|O_CREAT|O_TRUNC, mode);
close函数:int close(int fields);
每个打开的文件都有一个当前的偏移量,通常是一个非负整数。读写操作都会使得这个偏移量增加。
lseek函数:off_t lseek(int fields, off_t offset, int whence);返回当前偏移位置
参数whence可选常量:SEEK_SET从文件开头开始计算offset,SEEK_CUR从当前偏移量开始,SEEK_END从文件尾开始。
read函数:ssize_t read(int fields, void *buf, size_t nbytes);
若read成功,返回读入的字节数,若到达文件尾,返回0。
在Posix中,int read(int fields, char *buf, unsigned nbytes);
write函数: ssize_t write(int fields, const void *buf, size_t nbytes);返回值通常等于参数nbytes,除非发生出错。通常原因是磁盘写满或超出了进程分配的文件大小。
文件共享:Unix系统支持不同进程对文件共享。内核使用三种数据结构:process table entry,file table,v-node table。Process table包含两个字段:file descriptor flags和pointer to file table。File table有三个字段:file status flags(read write append sync等)、current file offset和pointer to v-node table。
原子性:pread 和 pwrite解决了lseek 再 read的问题
ssize_t pread(int fields, void *buf, size_t nbytes, offset);
ssize_t pwrite(int fields,void *buf, size_t nbytes, offset);
dup和dup2函数:int dup(int fields); int dup2(int fields, int fields2);复制file descriptor
sync,fsync和fdatasync函数:
传统的unix系统内核有一个buffer cache或page cache用于磁盘I/O。但写数据到文件,内核将数据拷到cache中进入写磁盘队列。为了保证磁盘上文件与cache中一致,提供了sync,fsync和fdatasync三个函数。
int fsync(int fields); int fdatasync(int fields); void sync(void);
fcntl函数:int fcntl(int fields, int cmd, …);
1 用于复制 cmd = F_DUPFD 2 用于获得/设置文件标识 cmd = F_GETFD/F_SETFD
3 获得/设置文件状态 cmd = F_GETFL/F_SETFL
4获得/设置异步I/O 所有者 cmd = F_GETOWN/F_SETOWN
5 获得/设置记录锁cmd = F_GETLK, F_SETLK , F_SETLKW |
|