![你能读到一个更新的mtime,但读到的内容却还没有更新吗?](https://linux22.com/image/107272/%E4%BD%A0%E8%83%BD%E8%AF%BB%E5%88%B0%E4%B8%80%E4%B8%AA%E6%9B%B4%E6%96%B0%E7%9A%84mtime%EF%BC%8C%E4%BD%86%E8%AF%BB%E5%88%B0%E7%9A%84%E5%86%85%E5%AE%B9%E5%8D%B4%E8%BF%98%E6%B2%A1%E6%9C%89%E6%9B%B4%E6%96%B0%E5%90%97%EF%BC%9F.png)
假设touch
不涉及等,只是标准open
, write
, close
,link
系统调用。
一个进程正在更新文件,另一个进程定期stat
查看它们是否已更改并重新加载内容。如果第二个进程在第一个进程完成写入之前重新加载,是否有可能以错误的文件视图结束?
主要关注 Linux ext4 文件系统,但如果其他文件系统有所不同,则这些信息可能会很有用。
答案1
POSIX 要求 read-after-write() 始终返回正确的数据,根据http://pubs.opengroup.org/onlinepubs/007908799/xsh/write.html:
对常规文件的 write() 成功返回后:
- 文件中被该写入修改的每个字节位置的任何成功的 read() 都将返回该位置的 write() 指定的数据,直到再次修改此类字节位置。
Linux 中文件 mtime 直到写入结束才更新,因此不应该可以看到更新的 mtime,而无需查看导致的数据那及时更新。
成功完成后,其中 nbyte 大于 0,write() 将标记为更新文件的 st_ctime 和 st_mtime 字段
Ext4 尝试确保 POSIX 兼容,因此在这种情况下您应该是安全的,但并非每个文件系统都完全兼容 POSIX,所以 YMMV。
答案2
取决于你想要什么粒度。单个write()
调用应该是原子的 (*)。但是,如果应用程序执行多个写入调用作为单个逻辑操作的一部分,则另一个进程可能会在中间唤醒以仅读取其中的一部分。
*) 系统调用仅写入部分数据后即可返回,这将在返回值中指示。但我不知道 Linux 上的本地文件是否会发生这种情况。
考虑这个序列:
--task 1-- --task 2--
write() ..
.. stat()
.. read()
write()
如果左侧的两个写入是单个逻辑修改的一部分,则任务 2 仅读取该修改的一部分。