php - 并发读写文件

标签 php linux file ubuntu concurrency

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

最佳答案

“最正确”的答案是:

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

一般情况下,读取和写入不保证是原子的。 readvwritev 系统调用是异常(exception)的,因为它们保证是原子的(至少在文件上)。然而,这不是“正常”写作所使用的。

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

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

请注意,一些 PHP 函数将在一些 体系结构上使用文件映射,这会使事情进一步复杂化。

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

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

关于php - 并发读写文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20314386/

相关文章:

PHP PDO 文件上传并保存到 MySQL 数据库导致模糊文件损坏

php - 通过一个其他表中的字段从表中选择行

php - 将 node.js 用于任务队列 worker 而不是其他语言有什么优势?

linux - macos命令行参数最后不起作用

php - 在最后一个完成之前不要运行 cron php 任务

javascript - 创建文件对象或 Blob

c - 动态地将文件中的文本读入字符串并删除c中的奇数字符

javascript - 如何在 JS/jQuery 中编写这个 php 数组函数?

javascript - 从属组合框

linux - 通过不可靠的网络链接同步文件 - 挂起而不是超时