gpt4 book ai didi

linux - mmap 是原子的吗?

转载 作者:行者123 更新时间:2023-12-04 21:28:25 26 4
gpt4 key购买 nike

mmap在它们的效果中调用原子?
也就是说,是否由 mmap 进行了映射更改以原子方式出现在访问受影响区域的其他线程中?
作为试金石,请考虑您执行 mmap 的情况。在一个全为零的文件中(来自线程 T1,此时是唯一的线程),然后启动从该区域读取的第二个线程 T2。然后,再次在 T1(原始线程)上执行第二个 mmap调用相同的区域,将映射替换为针对所有区域的文件的新映射。
阅读器线程是否有可能从某个页面读取一个 1(即,参见第二个 mmap 有效),然后随后从某个页面读取一个 0(即,参见第一个有效映射)?
您可以假设读取器线程上的读取被正确隔离,即上述效果不会仅仅由于 CPU/一致性级别的内存访问重新排序而发生。

最佳答案

Mmap(2)对于跨所有线程的映射是原子的;至少部分是因为 unmap(2)也是。分解一下,描述的场景类似于:

MapRegion(from, to, obj) {
Lock(&CurProc->map)
while MapIntersect(&CurProc->map, from, to, &range) {
MapUnMap(&CurProc->map, range.from, range.to)
MapObjectRemove(&CurProc->map, range.from, range.to)
}
MapInsert(&CurProcc->map, from, to, obj)
UnLock(&CurProc->map)
}
在此之后, map_unmap必须确保在删除映射时,没有线程可以访问它们。请注意 Lock(&thisproc->map) .
MapUnMap(map, from, to) {
foreach page in map.mmu[from .. to] {
update page structure to invalidate mapping
}
foreach cpu in map.HasUsed {
cause cpu to invoke tlb cache invalidation for (map, from, to)
}
}
第一阶段是重写处理器特定页表以使区域无效。
第二阶段是强制每个曾经将此映射加载到其翻译缓存中的 cpu 使该缓存无效。该位高度依赖于架构。在较旧的 x86 上,重写 cr3通常就足够了,所以 HasUsed真的是 CurrentlyUsing ;而较新的 amd64 可能能够缓存多个地址空间标识符, HasUsed 也是如此。 .在 ARM 上,本地 tlb 失效被广播到本地集群;所以 HasUsed将引用集群 ID 而不是 CPU 的 ID。更多详情,请搜索 tlb shootdown ,正如俗称的那样。
一旦这两个阶段完成,就没有 thread可以访问这个地址范围。任何这样做的尝试都会导致故障,这将导致 faulting thread锁定它的映射结构,该结构已经被 mapping thread 锁定,所以它会一直等到映射完成。映射完成后,所有旧映射都已删除并由新映射替换,因此在此之后无法检索先前的映射。
如果另一个 thread在更新期间引用地址范围?它将继续处理陈旧数据或出现故障。在这方面,陈旧数据并不是不一致的,就好像它在 mapping thread 之前被引用了一样。已进入 mmap(2) .故障情况与 faulting thread 相同以上。
总之,对映射的更新是使用一系列确保地址空间一致 View 的事务来实现的。这些交易的成本是特定于架构的。实现这一点的代码可能非常复杂,因为它需要防范隐式操作,例如推测性获取,以及显式操作。

关于linux - mmap 是原子的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59845919/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com