UNIX IO---再谈文件描述符
在 C 程序中,文件由文件指针或者文件描述符表示。ISO C 的标准 I/0 库函数(fopen, fclose, fread, fwrit
e, fscanf, fprintf 等)使用文件指针,UNIX 的 I/O 函数(open, close, read, write, ioctl)使用文件描述符。
下面重点来说下,文件描述符是如何工作的。
文件描述符相当于一个逻辑句柄,而 open,close 等函数则是将文件或者物理设备与句柄相关联。句柄是一个整数,
可以理解为进程特定的文件描述符表的索引。先介绍下面三个概念,后面讲下 open、close 等操作以后,文件和
文件描述符产生什么关系,以及 fork 后文件描述符的继承等问题。
文件描述符表:用户区的一部分,除非通过使用文件描述符的函数,否则程序无法对其进行访问。对进程中每个
打开的文件,文件描述符表都包含一个条目。
系统文件表:为系统中所有的进程共享。对每个活动的 open, 它都包含一个条目。每个系统文件表的条目都包含
文件偏移量、访问模式(读、写、or 读-写)以及指向它的文件描述符表的条目计数。
内存索引节点表: 对系统中的每个活动的文件(被某个进程打开了),内存中索引节点表都包含一个条目。几个系
统文件表条目可能对应于同一个内存索引节点表(不同进程打开同一个文件)。
1、举例: 执行 myfd = open( "/home/lucy/my.dat", O_RDONLY); 以后,上述 3 个表的关系原理图如下:
图 1
系统文件表包含一个偏移量,给出了文件当前的位置。若 2 个进程同时打开一个文件(如上图 A,B)做读操作,
每个进程都有自己相对于文件的偏移量,而且读入整个文件是独立于另一个进程的;如果 2 个进程打开同一个文
件做写操作,写操作是相互独立的,每个进程都可以重写另一个进程写入的内容。
如果上面进程在 open 以后又执行了 close()函数,操作系统会删除文件描述符表的第四个条目,和系统文件表
的对应条目(若指向它的描述符表唯一),并对内存索引节点表条目中的计数减 1,如果自减以后变为 0,说明没
有其他进程链接此文件,将索引节点表条目也删除,而这里进程 B 也在 open 这个文件,所以索引节点表条目保
留。
2、文件描述符的继承
通过 fork()创建子进程时,子进程继承父进程环境和上下文的大部分内容的拷贝,其中就包括文件描述符表。