linux - 在 fork 之前或之后对磁盘文件调用 mmap() 有什么区别?

标签 linux memory-management fork mmap

我一直在努力理解 mmap() 如何处理磁盘支持的文件,并且基本上明白了,但我仍然有这个问题。

在主进程 fork 一堆工作子进程和文件支持的只读 mmapped db 的情况下,mmaps 发生在 fork 之前的主进程还是子进程中是否重要?

我的理解是,如果发生在fork之前的master进程,那么在内存页表中,所有的mapped 页面被设置为在读取页面时产生页面错误,触发内核从磁盘(或页面缓存)加载页面,并且在 fork 之后,一个 child 读取页面将意味着该页面在mmap 准备好供其他 child 阅读而不会导致重大页面错误。

但是如果 mmap 发生在 fork 之后的子进程中,其他 worker 子进程是否可以从共享这些加载的页面中获益——它们实际上都使用相同的底层 mmap 吗?还是每个 worker child 都必须触发页面错误并自己加载每个页面?

最佳答案

这对页面错误事件没有影响。文件的页面映射对于操作系统来说是全局的,它表示特定页面是否在 RAM 中。每个具有文件映射的进程的 PTE 都指向这个公共(public)数据结构。只有第一个尝试访问不在 RAM 中的页面的进程才会出现页面错误。这将触发它被读入,并且尝试访问同一页面的其他进程将能够使用该 RAM。

这两种情况的一个区别是分配给映射 block 的虚拟地址是否相同。如果您在 fork 之前调用 mmap,则该地址将被复制到所有子项中。如果您在 fork 后调用 mmap,它们可能会获得不同的地址。如果需要,在所有进程中使用相同的地址允许您将指针传递到进程之间的映射 block 中。 block 内的对象之间可以有指针。如果它们不在同一地址,则需要使用偏移量,并且所有进程都必须将偏移量添加到基地址。

关于linux - 在 fork 之前或之后对磁盘文件调用 mmap() 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55872346/

相关文章:

linux - 在汇编中使用 printf 会导致管道输出为空,但在终端上有效

C++ 定时进程

linux - Linux TCP/IP 黑客 'live' 在哪里?

optimization - 两个纹理的非幂和内存消耗优化

ios - NSMutableRequest 对象主体的分配数据未被释放

c++ - C++中用户定义类的动态内存分配和自动分配的区别

c++ - fork() 2 children with pipeline, wait() 时出错

c - 如何在 C 中的 fork 进程上使用 POSIX 信号量?

linux - 在 CentOS_7 1908 上使用 FMXLinux 时出现错误

c++ - 访问结构中的字符指针