这是我到目前为止所了解的-虚拟和物理地址空间被分成相同大小的页面,假设100字节(仅作为示例),因此页面中可以寻址的地址从0到99,并且在需要给定的虚拟页时,会将其映射到物理内存。因此,在使用fork()
时,您将获得一个具有自己地址空间的单独进程,并从父进程中复制所有变量,这些变量现在位于子进程的地址空间中。我的第一个问题是-是否每个页面都从地址0开始,因为如果我在父级的地址空间中定义一个变量并从两个进程中打印它,它会给我相同的地址吗?第二个问题是-程序存储器由Text,Data,Heap,Stack组成,这是否是存储器中的全部一页?
答案 0 :(得分:1)
首先,我认为区分虚拟页面(或仅页面)和页面框架(在物理内存中)很重要。因此,页面帧实际上是物理RAM中的 ,并且可以将其映射到一个或多个进程的一个或多个虚拟地址。
一个页面可以寻址的地址从0到99,并且当需要给定的虚拟页面时,该地址将映射到物理内存中
这个主张对我来说听起来很奇怪。我不确定您的意思到底是什么。
因此,在使用
fork()
时,您将得到一个具有自己地址空间的单独进程,并从父进程中复制所有变量,这些变量现在位于子进程的地址空间中。
是,不是。 fork()
的作用是将父级的虚拟地址空间克隆到子进程中。此后,两个进程中的虚拟地址将相同,但是被复制,物理内存中具有相同的页面框架,但是现在使用复制将它们映射到另一个进程(子进程)在写。孩子尝试写入任何页面后,将触发pagefault
,操作系统将分配一个页面框架。
每个页面都从地址0开始吗,因为如果我在父级的地址空间中定义一个变量并从两个进程中打印它,它会给我相同的地址吗?
否,它只是与父节点共享相同的虚拟地址。如果启用了ASLR,则该地址是随机的(由父母的exec()
决定),并且如果您尝试多次执行,则该地址将有所不同。
程序存储器由Text,Data,Heap,Stack组成,这是存储器中的全部一页吗?
否,请重新考虑页面是什么。如果我们假设我们的系统有100个字节的页面,那么如果文本是1 KiB,那么我们将拥有11个页面...
此外,并非您命名的所有区域都映射在一起,但这取决于不同的系统。例如,带有ASLR的Linux将文本,数据和堆区域映射在一起,而堆栈和库是分开的。您可以在/proc/self/maps