手头有本《Unix环境高级编程 (APUE) 》,就在慢慢看,这两天把文件I/O看了看,现在总结一下。
这一章主要介绍的是非缓冲I/O(unbuffered I/O) ,表示每个read,write操作都进行一次系统调用,他不是标准C的一部分,是POSIX.1和single UNIX Specification的一部分。知识点有一下几个部分。
文件描述符:内核向进程返回的一个非负整数,读写文件或进行相关操作的时候用他来标识文件。标准输入0,标准输出1,标准错误输出2分别由符号常量STDIN_FINLENO,STDOUT_FILENO,STDERR_FILENO表示。文件描述符一般选择未用的最小数,不超过OPEN_MAX(大多为63).
open函数:
#include<fcntl.h>
int open( const char * filename, int flag, ../* mode_t */ );
出错时候返回-1,成功返回文件描述符
flag可以是读(O_RDONLY),写(O_WRONLY),读写(O_RDWR),注意着三者不能用|来合并。还有一些可选的常量,比如,O_APPEND表示每次写都添加到文件末尾,O_CREAT创建文件时候要指定第三个参数文件权限,O_TRUNC打开文件时候清空。
lseek函数:
#include<unistd.h>
off_t lseek( int fd, off_t offset, int whence ) ;
成功时候返回偏移量,否则返回-1,虽然说off_t可以为负值,但是返回的时候的意义是相对于文件文件开头(SEEK_SET)的。
whence有三种(SEEK_SET, SEEK_CUR,SEEK_END),分别是相对于文件开始,当前偏移量,和文件结尾。当用lseek确定好要操作的文件位置之后,就能在返回的偏移位置上进行读写了。如果文件描述的是一个管道,FIFO或者网络套接字,则lseek返回-1,并将errno设置为ESPIPE。
read函数:
#include<unistd.h>
ssize_t read( int fd, void *buf, size_t nbytes );
成功时候返回读入的字节数,出错返回-1
在很多中情况下,实际读到的字节数是比nbytes少的,比如说到达文件结尾,读取管道或者FIFO时候。
write函数:
#include<unistd.h>
ssize_t write(int fd, const void *buf, size_t nbytes );
成功时候返回已经写的字节数,否则返回-1
fcntl函数:
#include<fcntl.h>
int fcntl( int fd, int cmd, …/* int arg */ );
fcntl有5种功能:
1.复制一个现有的文件描述符(cmd=F_DUPFD ),可以实现dup和dup2的功能。
2.获得/设置文件描述符标记(cmd=F_GETFD,F_SETFD)。
3.获得/设置文件状态标志(cmd=F_GETFL,F_SETFD)。
4.获得/设置文件异步I/O所有权(cmd=F_GETOWN,F_SETOWN)。
5.获得/设置文件记录锁(cmd=F_GETLK,F_SETLK,F_SETLKW)。
pread,pwrite函数:
#include<unistd.h>
ssize_t pread( int fd, void *buf, size_t nbytes, off_t offset );
ssize_t pwrite( int fd, void *buf, size_t nbytes, off_t offset);
源自性操作,一次性进行定位和执行I/O。出错返回-1.
内核使用三种数据结构表示打开的文件:
1.每个进程在进程表中都有一个记录项,其中包含一张打开文件描述符表,每个文件描述符关联文件描述符标志和文件表项指针。
2.内核为所有打开文件维持一张文件表。包含文件状态标志(同步,读写,阻塞),当前偏移量,和指向文件v节点表项的指针。
3.每个打开的文件都有一个v-node结构包含了文件类型和对文件进行操作的函数的指针。v-node还包含了i-node信息(inode包含了文件所有者,文件长度,文件所在设备,指向数据块和磁盘所在位置的指针)。
当读写磁盘文件时候,以上函数是否有缓冲机制?
所有的磁盘I/O都要经过内核的块缓冲区,即内核的缓冲区高速缓存。read和write的数据都要被内核缓冲,那么不带缓冲的I/O指的是在用户进程中对这两个函数不会自动缓冲,每次write和read都要进行一次系统调用。
如果使用添加标志打开一个文件以便读,写,能否仍用lseek在任意位置开始读?能否用lseek更新文件中任意部分的数据?
可以。添加标志只对write有用。
沙了个发的..