当前位置: 代码迷 >> 综合 >> APUE 学习笔记(第三章)
  详细解决方案

APUE 学习笔记(第三章)

热度:5   发布时间:2024-01-09 06:34:27.0
APUE note 3(文件 I/O)

-v0.1 2014.12.14 *** draft
-v0.2 2014.12.19 *** add <4>
-v0.3 2014.12.21 *** add fcntl

本章讨论create, open, read, write,lseek等文件I/O函数。

1. 文件相关的几个数据结构:文件描述符,文件表,i node.
   每个进程有一个文件描述符表(用户态中), 用来指代这个进程打开的文件,文件描述符
   是0,1,2...这样的数字,对应的是一个个打开的文件。read(), write(), lseek()
   中指代文件的入参用文件描述符表。

   文件表是一个内核数据结构,每个进程打开的每个文件在内核里都有对应的一个结构
   来描述,所有的这样的结构组成文件表。每个这样的结构中包括,文件状态标志,文件
   偏移量,i node指针。

   open(path, oflag, ...); open函数的第二个入参,可以设置只读,只写等参数。这
   些参数最终被写到上面的文件状态标志中。当再调用read, write时,文件状态标志
   将起到判定的作用。

   这三个数据结构的关系见APUE上的图。

2. 缓冲概念:从硬盘上读数据,文件系统会做缓冲,这个在内核中。用户态的I/O也会坐
    缓冲,这个存在用户态的buffer中。数据写入硬盘,会经过用户态缓冲,内核文件系统
    缓冲,添加到写队列等步骤。

3. 多个进程写一个文件:如果是都在文件末尾写入,则lseek到文件末尾,再write写入,
   会出现竞争。用open(..,O_APPEND,..)可以避免。O_APPEND会设置文件状态标志,write
   时会查看文件状态标志,如果有O_APPEND则在文件末尾写入。

4. ./a.out 6>test
   在文件描述符6上打开文件test. 编译下面的代码,运行上面的命令。可以开到文件
   test中写入“12345”。以此类推:ls 2>>log, 在文件描述符2上打开文件,文件描述
   符2一般是错误错误输出,所以这样的命令把ls命令的错误输出写入log文件。

   command 6<>log, 是运行command的时候,在文件描述符6上,以读写的方式打开文件log。

        #include <unistd.h>#include <errno.h>char buffer[5] = {'1','2','3','4','5'};int main(void){int ret;int file;/* 把下面的5改成其他大于5的数,写入文件时会出错* 貌似是要输出几个buffer中的数据,这里的count就是多少,* 否则会出错*/		ret = write(6, buffer, 5);if (ret == -1) {perror("read read_test");return -1;}}
5. fcntl函数, 提供对文件描述符标志和文件状态标志的查询和修改。
   不清楚文中所说的文件描述符是什么? 下面得到的结果均是0

        fd = fcntl(0, F_GETFD);	printf("fd: %d\n", fd);fd = fcntl(1, F_GETFD);	printf("fd: %d\n", fd);fd = fcntl(2, F_GETFD);	printf("fd: %d\n", fd);
   文件状态标志位和上面的描述一致。fcntl可以复制文件描述符:fcntl(fd, F_DUPFD, fd_min),
   大于或等于fd_min的文件描述符将指向fd所指向的文件表项,相当于把fd复制到了fd_min