Unix系统支持在不同进程间共享打开的文件的结构是这样子的,来张图先有个每一印象:
内核使用三种数据结构表示打开的文件,它们之间的关系决定了在文件共享方面一个进程对另一个进程可能产生的影响。
(1) 第一个结构的说明:每个进程在进程表中都有一个记录项,记录项中包含有一张打开文件描述符表,可将其视为一个矢量,每个描述符占用一项。与每个文件描述符相关联的是:
(a) 文件描述符标识(close_on_exec)。
(b)指向一个文件表项的指针。
(2)第二个结构的说明:内核为所有的打开文件维持一张文件表。每个文件表项包含:
(a)文件状态标志(读、写、添加、同步和非阻塞等)。
(b)当前文件偏移量。
(c)指向该文件v节点的指针。
(3)第三个结构的说明:每个打开文件(或设备)都有一个v节点(v-node)结构。v节点包含了文件类型和对此文件进行各种操作的函数的指针。对于大多数文件,v节点还包含了该文件的i节点(i-node,索引节点)。这些信息是在打开文件时从磁盘上读入内存的,所以所有关于文件的信息都是快速可供使用的。例如,i节点包含了文件的所有者,文件长度,文件所在的设备,指向文件实际数据块在磁盘上所在位置的指针等等。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
两个进程同时打开同一个文件时是这样子的:
如果两个独立进程各自打开了同一个文件。我们假设第一个进程在文件描述符3上打开该文件,而另一个进程则在文件描述4上打开该文件。打开该文件的每一个进程都得到一个文件表项,但对一个给定的文件只有一个v节点表项。每个进程都有自己的文件表项的一个理由是:这种安排使每一个进程都有它自己的对该文件的当前偏移量。
- 在完成每个write后,在文件表项中的当前文件偏移量即增加所写的字节数。如果当前文件偏移量超过了当前文件长度,则在i节点表项中的当前文件长度被设置为当前文件的偏移量。
- 如果用O_APPEND标志打开了一个文件,则相应标志也被设置到文件表项的文件状态标志中。每次对这种具有添写标志的文件执行写操作时,在文件表项中的当前文件偏移量首先被设置为i节点表项中的文件长度。这就使得每次写的数据都添加到文件的当前尾端处。
- 若一个文件用lseek定位到文件当前的尾端,则文件表项中的当前文件偏移量被设置为i节点表项中的当前文件长度。注意,这与用O_APPEND标志打开文件是不同的。
- lseek函数只修改文件表项中的当前文件偏移量,没有进行任何文件I/O操作。
可能有多个文件描述符指向同一个文件表项。在下一小节中讨论dup函数时,我们将能看见这一点。