【问题标题】:What is the difference between calling mmap() on a disk file before or after a fork?在分叉之前或之后对磁盘文件调用 mmap() 有什么区别?
【发布时间】:2019-04-26 17:21:11
【问题描述】:

我一直在努力了解 mmap() 如何处理磁盘支持的文件,并且大部分时间都在了解它,但我仍然有这个问题。

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

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

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

【问题讨论】:

  • 页面错误并非特定于进程。文件的一页在内存中,或者不在内存中。
  • @Barmar 这也不完全正确。页面错误中断在触及用户空间地址时是特定于进程的
  • @AnttiHaapala 是不是因为它们可以有不同的保护模式(同一个页面在P1中可以只读但在P2中可以读写),所以它们必须通过缺页机制来检查这?是否必须分页内存仍然没有区别。

标签: linux memory-management fork mmap


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2020-03-04
    • 1970-01-01
    • 1970-01-01
    • 2013-01-22
    • 1970-01-01
    • 2013-10-05
    • 2015-04-19
    • 1970-01-01
    • 2020-03-26
    相关资源
    最近更新 更多