什么时候O_SYNC写入在pagecache(mmap'd文件)中可见?

时间:2011-08-15 05:17:10

标签: linux sync mmap

我有一个mmap'd只读/共享文件,多个线程/进程同时读取数据。允许单个编写器随时修改数据(在单独的共享内存区域中使用互斥锁)。使用基础文件上的write()执行更改。整体设置是数据库的一部分,旨在实现事务一致性。

将以任何顺序写出许多任意数据页,然后调用fdatasync()。在写入根页之前,文件中的任何内容都不指向这些更改的页面。使用使用O_SYNC打开的第二个文件描述符编写根页面,因此在成功写入根页面之前,写入不会返回。所有正在编写的页面都是mmap区域的一部分,因此它们最终会对所有读者都可见。

问题是 - 只要内核将用户缓冲区复制到页面缓存中,最终的O_SYNC写入是否立即可见?或者仅在同步写入完成后才可见?我已经通过内核代码阅读了一下但没有完全遵循它;它看起来像用户数据被立即复制到页面缓存,然后调度写入,然后它等待写入完成。同时,写入的数据已经存在于页面缓存中,因此读取器进程立即可见。这是不可取的,因为如果物理写入实际上失败,则必须回滚事务,并且永远不允许读者看到由不成功的事务写入的任何内容。

任何人都知道O_SYNC写入如何与页面缓存交互?我想只是为了安全,我可以使用互斥锁包装对根页面的访问,但这会增加一层最好避免的开销。

2 个答案:

答案 0 :(得分:2)

根据正式的POSIX标准,MAP_SHARED区域的更新可随时出现。同步I / O定义指定只有在数据登陆物理介质后才会返回写入,但不会讨论其他进程看到的数据。

在Linux上的实践中,它可以像您所描述的那样工作 - 页面缓存是调度设备写入的暂存区域,MAP_SHARED映射是页面缓存的视图。

作为替代方案,您可以将根页的副本放入共享的匿名区域。读取过程将使用该副本,并且写入过程将在将根页面同步到磁盘后更新它。您仍然需要同步,因为您无法以原子方式更新整个页面。

答案 1 :(得分:0)

您应该将msync(2)用于mmapped文件。混合写入和mmapped访问是一个麻烦。