一.文件描述符

文件描述符 fd (file desciptor)在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于 UNIX , Linux 这样的操作系统。

二. 文件描述符相关的数据结构

Linux 内核用三个相关的数据结构来表示打开的文件:

1.描述符表即 descriptor table 。每个进程都有自己独立的描述符表,它的表项是由进程打开的文件描述符来索引的。每个打开的描述符表项指向文件表中的一个表项。

2.文件表即 file table 。打开文件的集合是由一张文件表来表示的,所有的进程共享这张表。每个文件表的表项组成包括当前文件位置,引用计数(即当前指向该表项的描述符表项数),以及一个指向 v-node 表中对应表项的指针。关闭一个描述符会减少相应的文件表表项中的引用计数。内核不会删除这个文件表表项,知道它的引用计数为零。

3.v-node 表 (v-node table)也称 i-node 表。同文件表一样,所有的进程共享这张 v-node 表。每个表项包含 stat 结构中的大多数信息,包括 st_mode 和 st_size 成员。

Linux 中规定了 标准输入文件的 fd = 0,标准输出的 fd = 1,标准错误的 fd = 2 。

下图一 展示了一个示例,形象的说明一下三个结构的关系,其中描述符 1 和 4 通过不同的打开文件表项来引用两个不同的文件。这是一种典型的情况,没有共享文件,并且每个描述符对应一个不同的文件。

                                                                                    图一

 

如下图二所示,多个描述符也可以通过不同的文件表表项来引用同一个文件。例如,如果以同一个 filename 调用 open 函数两次,就会发生这种情况。关键思想是每个描述符都有它自己的文件位置,所以对不同描述符的读操作可以从文件的不同位置获取数据。

                                                                          图二

这个例子展示了两个文件描述符通过两个打开文件表表项共享同一个磁盘文件。

假设在调用 fork 之前,父进程有图一所示的打开文件。然后,调用 fork 后的情况如下图三所示。子进程有一个父进程描述符表的副本。父子进程共享相同的打开文件表集合,因此共享相同的文件位置。

                                                                     图三

 

Logo

更多推荐