【APUE】第3章 文件I/O (3) 文件共享、原子操作、函数dup/dum2、函数sync/fsync/fdatasync、函数fcntl、函数ioct1、目录/dev/fd 使用说明

1、文件共享

UNIX系统支持在不同的进程间共享打开文件。为了说明这种共享,以下介绍内核用于所有I/O的数据结构。

内核使用3种数据结构表示打开文件,它们之间的关系决定了在文件共享方面一个进程对另一个进程可能产生的影响。

(1)每个进程在进程表中都有一个记录项,记录项中包含一张打开文件描述符表,可将其视为一个矢量每个描述符占用一项。与每个文件描述符相关联的是:

  • 文件描述符标志;
  • 指向一个文件表项的指针。

(2)内核为所有打开文件维护一张文件表。每个文件表项包含:

  • 文件状态标志(读、写、添加、同步和非阻塞等);
  • 当前文件偏移量
  • 指向该文件v节点表项的指针。

(3)每个打开文件(或设备)都有一个v节点(v-node)结构。v节点包含了文件类型和对此文件进行各种操作函数的指针。对于大多数文件,v节点还包含了该文件的i节点(i-node,索引节点)。这些信息都是在打开文件时从磁盘上读入内存的,所以文件的所有相关信息都是随时可用的。例如i节点包含了文件的所有者、文件长度、指向文件实际数据块在磁盘上的位置等。(注意在linux中是没有v节点结构的但是存在i节点结构)

如图3-7 显示了一个进程对应的3张表之间的关系。该进程有两个不同的打开文件;一个文件从标准输入打开(文件描述符为0),另一个从标准输出打开(文件描述符为1)。

如果两个独立的进行各自打开了同一个文件,则有如图3-8所示的关系。

我们假定第一个进程在文件描述符3上打开该文件,而另一个进程在文件描述符4上打开该文件。打开该文件的每个进程都获得各自的一个文件表项,但是对于一个给定的文件只有一个v节点表项之所以每个进程都获得自己的文件表项,是因为这可以是每个进程都有它自己的对该文件的偏移量

给出了这些数据结构之后,现在对前面所述的操作做进一步说明:

(1)在完成每个write后,文件表项中的当前文件偏移量即增加所写入的字节数。如果这导致当前文件偏移量超出当前文件长度,则将i节点表项中的当前文件长度设置为当前文件偏移量(也就是该文件加长了)。

(2)如果使用O_APPEND标志打开一个文件,则相应标志也被设置到文件表项的文件状态标志中。每次对这种具有追加标志的文件进行写操作时,文件表项中的当前文件偏移量首先将会被设置为i节点表项中的当前文件长度。

(3)若一个用lseek定位到文件当前的末尾,则文件表项中的当前偏移量被设置为i节点表项中的当前文件长度。

(4)lseek函数只修改文件表项中的当前文件偏移量,不进行任何I/O操作。

可能有多个文件描述符指向同一文件表项,例如fork后,此时父子进程各自的每一个打开文件描述符共享一个文件表项。

上述介绍的一切对于多个进程读取一个文件都能正确工作。每个进程都有自己的文件表项,其中也有它自己的当前文件偏移量。但是当多个进程同一个文件时,则可能产生预想不到的结果。为了说明如何避免这种情况,需要先理解原子操作的概念。

2、原子操作

猜你喜欢

转载自www.cnblogs.com/xuelisheng/p/10800686.html