同时读写文件

时间:2013-12-01 16:27:40

标签: php linux file ubuntu concurrency

在Linux上,如果一个脚本正在读取(大)文件而另一个脚本正在尝试写入同一个文件,那么这两个操作是否会成功,以便第一个脚本读取未损坏的数据(因为inode)? (假设我正在使用file_get_contentsfile_put_contents

1 个答案:

答案 0 :(得分:3)

“最正确”的答案是:

虽然小字体有点复杂:两种操作都会成功,并且您绝不会在最严格的措辞中看到损坏的数据。但是,您看到的数据可能不一致。这意味着如果您编写“ABC”,那么在某人正在阅读之前可以实现写“AB”(并且最后一位数据将是之前文件中的任何内容),但“ABC”将永远不会被破坏为“pnt”或“干熄焦”。
此外,如果两个进程同时写入,则可能在实现另一个之前仅实现一个写入的一部分。例如,同时写入“ABCDEF”和“123456”可能导致“A2C4E6”存储在缓冲区缓存中,随后存储在磁盘上。 可能也会导致“ABCDEF”或“123456”。同时阅读的第三个过程可能会找到任何可能的组合。

一般来说,读取和写入不保证是原子的。 readvwritev系统调用是例外的,因为它们保证是原子的(至少在文件上)。然而,这不是“正常”写入使用的内容。

此外,通常会发生库级缓存,因此除了读取和写入不一定在缓冲区缓存中是原子的,同时读取和写入的两个进程可能对文件内容的含义有很大不同。

附加到文件(非并发)并且同时读取通常是“安全的”。阅读时并非所有数据都可见,但无论你写什么,最终都会以你写的方式结束。

请注意,某些 PHP函数将在某些体系结构上使用文件映射,这会使事情变得更加复杂。

回复编辑: file_get_contentsfile_put_contents正好是前面提到的一些在某些架构上使用内存映射的函数。
没有详细说明哪种架构,但Linux是一个相当安全的赌注 现在内存映射的问题在于,并发访问文件的两个进程有效地同时访问同一个物理内存。这意味着在没有显式同步的情况下,读取和写入再次是不是原子。

此外,您没有正式保证(尽管实现几乎保证它,因为Linux具有统一的虚拟内存系统),内存中的视图对应于除非已调用msync,否则可在外部观察磁盘表示。这意味着理论上(虽然不是在实践中)使用正常读写(不使用内存映射)的不同进程可能会看到完全不同的东西。