【问题标题】:fork() and virtual address spacesfork() 和虚拟地址空间
【发布时间】:2018-08-09 09:56:22
【问题描述】:

这是我到目前为止所理解的 - 虚拟和物理地址空间被划分为具有相同大小的页面,比如说 100 个字节(仅用于示例),所以一个页面中可以寻址的地址是从 0 到99,当需要给定的虚拟页面时,它被映射到物理内存。因此,当使用fork() 时,您将获得一个具有自己地址空间的单独进程,并从现在位于子地址空间中的父进程中复制所有变量。我的第一个问题是 - 每个页面是否都从地址 0 开始,因为如果我在父地址空间中定义一个变量并从两个进程打印它,它会给我相同的地址吗?第二个问题是 - 程序内存由文本、数据、堆、堆栈组成,这都是内存中的一页吗?

【问题讨论】:

    标签: c memory fork


    【解决方案1】:

    首先,我认为区分虚拟页面(或仅页面)和页面框架(在物理内存中)很重要。因此,页框是物理内存中的真正,它可以映射到一个或多个进程的一个或多个虚拟地址。

    一个页面中可以寻址的地址是从0到99,当需要给定的虚拟页面时,它会映射到物理内存

    这个断言对我来说听起来很奇怪。我不确定你在这里的确切意思。

    因此,当使用fork() 时,您将获得一个具有自己地址空间的单独进程,并从现在位于子地址空间中的父进程中复制所有变量。

    是和不是。 fork() 所做的就是将父进程的虚拟地址空间克隆到子进程中。之后,两个进程中的虚拟地址将相同,但并非所有内容都复制。物理内存中有相同的页框,但现在它们使用写时复制映射到另一个进程(子进程)。一旦孩子尝试写入任何页面,它将触发pagefault,并且操作系统将分配一个页面框架。

    是否每个页面都从地址 0 开始,因为如果我在父地址空间中定义一个变量并从两个进程打印它,它会给我相同的地址吗?

    不,它只是与父节点共享相同的虚拟地址。如果启用了 ASLR,则该地址是随机的(由父级的 exec() 决定),如果您尝试多次执行,它会有所不同。

    程序内存由Text,Data,Heap,Stack组成,这都是内存中的一页吗?

    不,再想想什么是页面。如果我们假设我们的系统有 100 字节的页面,如果文本是 1 KiB,我们将有 11 个页面...... 此外,并不是你命名的所有区域都映射在一起,而是取决于不同的系统。例如,带有 ASLR 的 Linux 将文本、数据和堆区域映射在一起,而堆栈和库是分开的。您可以查看/proc/self/maps中的示例

    【讨论】:

    • 我相信 ASLR 发生在程序被exec() 加载到地址空间时,而不是在进程被分叉时发生。
    • 是的,没错,我没有说反话。在我的示例中,ASLR 应用于父进程,虚拟地址空间与子进程共享。谢谢我编辑了答案只是为了澄清这一点。
    猜你喜欢
    • 2021-03-18
    • 2016-01-13
    • 1970-01-01
    • 2023-03-17
    • 2019-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多