【问题标题】:While "fork"ing a process, why does Linux kernel copy the content of kernel page table for every newly created process?在“分叉”一个进程时,为什么 Linux 内核会为每个新创建的进程复制内核页表的内容?
【发布时间】:2015-01-29 02:01:54
【问题描述】:

以下讨论适用于 32 位 ARM Linux 内核。

我注意到在fork过程中,Linux内核将内核页表(master page table,即swapper_pg_dir)的内容复制到每个新创建的进程的页表中。

问题是:

  • 为什么要这么做呢?
  • 为什么所有进程不能共享一个内核页面副本 表(关于 32 位 ARM Linux 的更高 1G 部分),而不是 memcpy 每个新创建的进程的交换页表?
  • 是不是很浪费内存?

相关源码(“-->”代表函数调用):
do_fork --> copy_process --> copy_mm --> dup_mm --> mm_init --> mm_alloc_pgd --> pgd_alloc -->

/*
* Copy over the kernel and IO PGD entries
*/
init_pgd = pgd_offset_k(0);

memcpy(new_pgd + USER_PTRS_PER_PGD, init_pgd + USER_PTRS_PER_PGD,
       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));

【问题讨论】:

  • 只有一个物理MMU;它是硬件。每个进程都需要一个完整的 1 级表 (16K)。对于内核,大多数是节/超节,大小为 1MB,没有 L2。进程可以共享 L2 条目。
  • 感谢您的评论。你的意思是说因为只有一个物理MMU,如果内核母版页表(swapper page table)只有一个副本,那么每次内核/用户模式切换时都需要刷新MMU?
  • 不,每个进程可能有一个连续的 16k 单独的 L1 表。切换表底座时,必须刷新所有 L1-TLB。但是,我认为 Linux 只更新 real L1 页表,并为每次更新进行 TLB 刷新;在 ARM 上有一些假的页表。抱歉,我没有看什么是 swapper_pg_dir;真实表或伪表。 Linux 有 arch 依赖/独立代码。
  • 所以我的理解是如果 -所有进程共享相同的内核母版页表的单个副本以用于较高的 1GB 部分(内核土地)-所有进程对较低的 3GB 部分使用单独的页表(用户空间) 这意味着进程没有连续的 16K L1 表,因此每次内核-用户切换时都需要切换页表。 请您确认一下吗?谢谢!
  • 您好,从源码看,内核页表没有完全复制。实际上只拷贝了page全局目录,也就是说进程页表和内核页表指向同一个pud、pmd和pte。

标签: c linux memory-management linux-kernel arm


【解决方案1】:

每个进程都有自己的内核部分页表副本(更高的 1GB)是为了在切换用户/内核域时避免 L1 页表切换(即避免更新 TTBR)。请注意,用户/内核域切换非常频繁。

为什么要避免更新 TTBR?详细信息可以在这里找到: What is the downside of updating ARM TTBR(Translate Table Base Register)?

【讨论】:

    【解决方案2】:

    共享页表意味着共享内存空间。换句话说,它破坏了拥有操作系统的意义。每个进程都有自己的页面故事。页表不占用太多内存。

    【讨论】:

    • 感谢您的回答。我的观点是,为什么要将母版页表的“内容”复制到每个新创建的进程的页表中?为什么每个进程不能共享同一个内核页表(高1G部分)
    猜你喜欢
    • 2011-12-22
    • 2015-02-20
    • 2011-01-27
    • 2017-09-19
    • 1970-01-01
    • 2020-09-23
    • 1970-01-01
    • 1970-01-01
    • 2020-04-20
    相关资源
    最近更新 更多