第三章:文件I/O
Linux对文件操作有open、read、write、close、lseek,这些api都是不带缓冲的函数,相对于c库,这些可移植的api内部实现是有缓冲区的。
int open(char* pathname, int flag, …);
int read(int fd, void* buf, size_t size);
int write(int fd, void* bud, size_t size);
off_t lseek(fd, off_t offset, int whence);
int close(int fd);
当一个进程终止的时候,操作系统会释放 分配的内存和关闭打开的文件描述符。
off_t 可以是4个字节或者是8个字节,可以设置宏_FILE_OFFSET_BITS设置为64位
来支持打开的文件超过2G。
open的时候 flag中有O_CREAT 标志,当文件不存在会创建文件,存在不报错。
读写I/O的效率(regular file)一般都是文件所在分区的blocksize作为一次读写操作的缓冲区的大小,这样效率是最高的,需要的时候是最少的[l1] 。
文件共享:
三个表项分别是进程记录项、文件表项、文件对应的v节点
其中进程记录项中有两项:
文件描述符标志:对于每一个fd都有自己的文件描述符标志
指向文件表项指针:不同的文件描述符可能一样,比如dup函数,复制出来的描述符共享文件表项,但是文件描述符可以不同。fork子进程的时候,父子进程共享同一个文件表项
文件表项:
文件状态标志:是文件打开的时候的标志,可读、可写、可读写…
当前文件偏移:是这个文件当前独到哪里(lseek可以查看)
系统v节点:指向系统v节点指针
v节点信息:
v节点包含对文件操作的内核调用接口,比如你对一个描述符调用read的时候会从用户态进入到内核态,把用户态传入的参数,转交给内核态对应read的参数,指向内核态的函数,这些函数才是和文件系统打交道的。
i节点,一般包含文件的所有者、文件长度、文件所在设备。。。(stat可查看)
注意文件描述符标志和文件状态标志在作用域方面的区别,前者仅仅适用一个进程的一个描述符,而后者适用于指向该给定文件表项的任何进程中的描述符(父子进程共享)。
int dup(int fd);
int dup2(int fd, int fd2);
dup2如果fd2存在,就关闭这个描述符,如果不存在就适用fd2作为赋值的结果,如果fd ==fd2就直接返回fd。
dup、dup2共享一个文件表项。但是新复制出来的描述符的标志和原来的可以不一样。
强大的fcntl:
int fcntl(int fd, int cmd,…)
1 复制现有的描述符(cmd=F_DUPFD)共享同一个文件表项
2 获取或设置文件描述符标志(cmd=F_GETFD、cmd= F_SETFD)
3 获取或设置文件状态标志(cmd = F_GETFL、cmd=F_SETFL)
4 获取或设置异步I/O所有权(cmd=F_GETOWN、cmd=F_SETOWN)
5 获取或设置记录锁(cmd=F_GETLK、cmd=F_SETLK、cmd=F_SETLKW)