linux下多进程并发写同一个文件(Linux应用编程篇) |
您所在的位置:网站首页 › pyqt5多线程读写同一个文件 › linux下多进程并发写同一个文件(Linux应用编程篇) |
其实两个进程访问同一个文件的时候,你记住一句话: 读时共享,写时独占 1. 文件共享 Unix系统支持在不同进程间共享打开的文件。为此,我们先介绍一下内核用于所有I/O的数据结构。注意,下面的说明是概念性的,与特定的实现可能匹配,也可能不匹配。 内核使用三种数据结构表示打开的文件,它们之间的关系决定了在文件共享方面一个进程对另一个进程可能产生的影响。 1、每个进程在进程表中都有一个记录项,记录项中包含有一张打开文件描述符表,可将其视为一个矢量,每个描述符占用一项。与每个文件描述符相关联的是: (a) 文件描述符标识(close_on_exec)(b)指向一个文件表项的指针。 2、内核为所有的打开文件维持一张文件表。每个文件表项包含: (a)文件状态标志(读、写、添加、同步和非阻塞等)。 (b)当前文件偏移量。 (c)指向该文件v节点的指针。 3、每个打开文件(或设备)都有一个v节点(v-node)结构。v节点包含了文件类型和对此文件进行各种操作的函数的指针。对于大多数文件,v节点还包含了该文件的i节点(i-node,索引节点)。这些信息是在打开文件时从磁盘上读入内存的,所以所有关于文件的信息都是快速可供使用的。例如,i节点包含了文件的所有者,文件长度,文件所在的设备,指向文件实际数据块在磁盘上所在位置的指针等等。 我们忽略了默写实现细节,但这并不影响我们的讨论。例如,打开文件描述符表可存放在用户控件,而非进程表中。这些表也可以用于多种方式的实现,不必一定是数组;例如,可将它们实现为结构的连接表。这些细节并不影响我们在文件共享方面的讨论。 下图(打开文件的内核数据结构)显示了一个进程的三张表之间的关系。该进程有两个不同的打开文件:一个文件打开为标注输入(文件描述符为0),另一个打开为标准输出(文件描述符为1)。 下面是两个独立进程各自打开同一个文件 给出了这种数据结构后,现在对前面所描述的操作做进一步说明。 在完成每个write后,在文件表项中的当前文件偏移量即增加所写的字节数。如果当前文件偏移量超过了当前文件长度,则在i节点表项中的当前文件长度被设置为当前文件的偏移量。 如果用O_APPEND标志打开了一个文件,则相应标志也被设置到文件表项的文件状态标志中。每次对这种具有添写标志的文件执行写操作时,在文件表项中的当前文件偏移量首先被设置为i节点表项中的文件长度。这就使得每次写的数据都添加到文件的当前尾端处。 若一个文件用lseek定位到文件当前的尾端,则文件表项中的当前文件偏移量被设置为i节点表项中的当前文件长度。注意,这与用O_APPEND标志打开文件是不同的。 sleek函数只修改文件表项中的当前文件偏移量,没有进行任何文件I/O操作。 可能有多个文件描述符指向同一个文件表项。在下一小节中讨论dup函数时,我们将能看见这一点。函数调用fork后产生的父子进程中,它们共享相同的i或v节点和同一个文件表项。(通过在现代Linux系统中进行测试得到的,测试程序和结构见下文(更正:测试结果分析有误!已更正!))。 注意:文件描述符标志和文件状态标志在作用域方面的区别,前者只用于一个进程的一个描述符,而后者适用于指向该给定文件表项的任何进程中的所有描述符。上面所述的一切对多个进程读同一个文件都能正确工作。每个进程都有它自己的文件表项,其中也有它自己的当前文件偏移量。但是,当多个进程写同一个文件时,则可能产生预期不到得结果。为了说明如何避免这种情况,我们需要理解原子操作的概念。 2. 原子操作 2.1 添写至一个文件 考虑一个进程,它要将数据添加到一个文件尾端。早期的UNIX系统版本并不支持open的O_APPEND选项,所以程序被编写成下列形式: if (lseek(fd, 0L, 2) |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |