【问题标题】:How does kernel know about physical pages are shared by two different processes?内核如何知道物理页面由两个不同的进程共享?
【发布时间】:2012-04-21 12:36:34
【问题描述】:

我们知道页表是用来从虚拟内存页地址中获取物理内存页地址的。但是,内核如何知道一个物理内存页面是否由不同的进程共享(例如在分叉进程及其父进程的情况下)。这样的清单保存在哪里?

【问题讨论】:

    标签: c linux x86-64


    【解决方案1】:

    内核是创建所有虚拟映射的实体。所以它确切地知道什么是共享的,什么不是。如果没有内核的帮助,用户空间进程无法创建共享映射。

    当进程请求分叉时,内核还负责复制映射。它包含所需的所有信息。

    一个页面的映射数量保存在代表该页面的struct page 结构中的一个字段中。每次创建新映射时它都会增加,而当映射消失时它会减少。

    如果你想更深入地研究这个,你可以访问Linux-MM。特别是,请阅读文档部分中链接(免费提供的 PDF)Mel Gorman 的 Understanding the Linux Virtual Memory Manager 书(非常技术性)。

    【讨论】:

    • 在fork(copy-on-write)的情况下,内核如何知道原来的进程正在尝试写,从而给它另一个物理页(copy-on-write) ?它是否授予对原始和分叉进程页面的只读访问权限。所以如果原始进程修改它,它会给它一个新的物理页面,但是如果分叉的进程后来也修改了这个页面怎么办。内核如何决定它不需要给它一个新的物理页面并且可以使用旧的,因为现在它与原始进程不同。
    • 示意性地,最初由两个进程共享的页面被标记为只读。当任一进程尝试写入时,会产生错误,内核会复制页面并更新进程的映射。新创建的页面和原始页面都设置为读/写,不需要对其进行进一步的操作。父母或孩子先尝试写入并不重要。
    • 好的,我明白了。但是当我们在 MMU 级别说“只读”时,它是属于物理页面还是虚拟内存页面?
    • 虚拟地址。 (顺便说一句,我之前的评论在技术上是不准确的,实际情况并非如此,如果您想了解血淋淋的细节,请参阅链接的书。)
    【解决方案2】:

    引用自CSAPP 3rd,Linux 内核进程的虚拟内存视图

    pgd,它指向一级页表(页全局目录)的基础,mmap,它指向一个 vm_area_structs(区域结构)的列表,每一个都表征一个当前虚拟地址空间的区域。当内核运行这个进程时,它会将pgd存储在CR3控制寄存器中。

    • fvm_start。指向区域的起点。
    • vm_end。指向区域的末端。
    • vm_prot。描述该区域中包含的所有页面的读/写权限。
    • vm_flags。描述(除其他外)该区域中的页面是与其他进程共享还是该进程私有。
    • vm_next。指向列表中的下一个区域结构。

    当当前进程调用fork函数时,内核会为新进程创建各种数据结构并为其分配一个唯一的PID。要为新进程创建虚拟内存,它会创建当前进程的 mm_struct、区域结构和页表的精确副本。它将两个进程中的每个页面标记为只读,并将两个进程中的每个区域结构标记为写时私有复制。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-02
      • 2015-11-06
      • 1970-01-01
      • 1970-01-01
      • 2012-09-11
      • 2014-12-11
      • 2019-05-10
      • 2018-07-01
      相关资源
      最近更新 更多