【发布时间】:2020-05-07 19:09:55
【问题描述】:
mmap 调用的效果是原子的吗?
也就是说,mmap 所做的映射更改对访问受影响区域的其他线程来说是原子的吗?
作为一个试金石,考虑一下你在一个全为零的文件中执行mmap 的情况(来自线程T1,这是此时唯一的线程),然后启动第二个线程T2 从区域读取。然后,再次在 T1(原始线程)上对同一区域进行第二次 mmap 调用,将映射替换为针对所有文件的新映射。
阅读器线程是否有可能从某个页面读取一个 1(即,参见第二个 mmap),然后随后从某个页面读取一个 0(即,参见第一个映射有效)?
您可以假设读取器线程上的读取被正确隔离,即上述效果不会仅由于 CPU/一致性级别的内存访问重新排序而发生。
【问题讨论】:
-
是否有可能任何阅读器线程从某个页面读取一个(即,参见第二个有效的 mmap),然后从某个页面读取一个零(即,参见第一个映射有效)? 如果没有对此进行足够的思考以实际制定答案,我认为您不能排除以任何顺序替换页面的可能性。如果多个页面被替换,我怀疑没有原子性或任何排序保证。
-
@AndrewHenle - 确实,除非内核在更新映射时暂停所有进程线程,或者如果要离线创建一个带有更改的全新映射然后交换页表指针(例如, CR3 on x86) 到新的映射,很难看出它是原子的,但我准备好感到惊讶了......
-
Re,来自两个不同线程的两个冲突、不同步的 mmap 调用,都试图映射同一个 VM 区域。我当然希望两个 mmap 调用之一会失败。但就个人而言,我不会太担心如何它会失败的确切细节,因为我永远不会故意编写一个依赖于以任何特定方式解决种族问题的程序。
-
@SolomonSlow - 情况并非如此:两个
mmap调用来自同一个线程,这里只有一个线程调用mmap。显然,我希望mmap调用对于进行调用的线程来说是原子的(即,mmap在返回后从代码的 POV 中完全生效),但问题是关于第二个线程从(或写入)受mmap调用影响的区域。我会尽量澄清这个问题。 -
我认为一个线程访问一块虚拟地址空间是不合法的,而该地址空间的映射可能正在改变。据我所知,没有任何保证,操作可能会出错甚至损坏东西。它不仅不是原子的,还允许首先取消映射所有页面,然后以任何顺序开始映射新页面,或者以任何它想要的方式进行操作,只要它不会破坏未被操作更改的页面。跨度>
标签: linux multithreading concurrency mmap memory-mapping