内核使用三种数据结构表示打开的文件,它们之间的关系决定了在文件共享方面一个进程对另一个进程可能产生的影响。
- (1)每个进程在进程表中都有一个记录项,记录项中包含有一张打开文件描述符表,可将其视为一个矢量,每个描述符占用一项。与每个文件描述符相关联的是:
- 文件描述符标志(close_on_exec)。
- 指向一个文件表项的指针。
(2)内核为所有打开文件维持一张文件表。每个文件表项包含:
- 文件状态标志(读、写、添写、同步和非阻塞等)。
- 当前文件偏移量。
- 指向该文件v节点表项的指针。
(3)每个打开文件(或设备)都有一个v节点(v-node)结构。v节点包含了文件类型和对此文件进行各种操作的函数的指针。对于大多数文件,v节点还包含了该文件的i节点(i-node,索引节点)。i节点包含了文件的所有者、文件长度、文件所在的设备、指向文件实际数据块在磁盘上所在位置的指针。
打开文件描述符表可以存放在用户空间,而非进程表中。
一个进程打开两个不同的文件:
图3.1 打开文件的内核数据结构(一个进程打开两个不同的文件)
两个独立进程各自打开同一个文件:
图3.2 两个独立进程各自打开同一个文件
每个进程都有自己的文件表项的一个理由是:这种安排使每个进程都有它自己对该文件的当前偏移量。
可能有多个文件描述符项指向同一文件表项。例如,在fork后,父子进程对于每一个打开文件描述符共享同一个文件表项。
注意,文件描述标志和文件状态标志在作用域方面的区别,前者只用于一个进程的一个描述符,而后者则适用于指向该给定文件表项的任何进程中的所有描述符。