【问题标题】:Reading and writing files concurrently同时读取和写入文件
【发布时间】:2013-12-17 08:09:36
【问题描述】:

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

【问题讨论】:

  • 答案可能是“视情况而定”。这取决于您用于文件访问的功能。你有什么特别的想法吗?
  • @MaxK file_get_contents 和 file_put_contents
  • @DesmondHume:这些正是我在下面最后一段中提到的有问题的少数“一些功能”。这些将在某些架构上使用文件映射,而不会在其他架构上使用。

标签: php linux file ubuntu concurrency


【解决方案1】:

“最正确”的答案是:

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

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

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

附加到文件(非并发)和并发读取通常是“安全的”。并非所有数据在您阅读时都是可见的,但无论您写什么,最终都会完全按照您写的方式。

请注意,some PHP 函数将在 some 架构上使用文件映射,这使事情变得更加复杂。

回复编辑: file_get_contentsfile_put_contents 正是前面提到的一些函数,它们将在某些架构上使用内存映射。
没有具体说明具体的架构,但 Linux 是一个相当安全的选择。
现在内存映射的问题在于,同时访问一个文件的两个进程实际上是在同时访问同一个物理内存。这意味着读取和写入再次不是在没有显式同步的情况下是原子的。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-30
    • 2017-06-22
    • 2013-01-06
    相关资源
    最近更新 更多