调用fork时,堆栈和堆都从父进程复制到子进程。在使用fork系统调用之前,我在malloc()中有一些内存;让我们说它的地址是A.在使用fork系统调用之后,我在父进程和子进程中打印了这个内存的地址。我看到两者都打印相同的地址:A。子进程和父进程能够独立地向该地址写入任何值,并且一个进程的修改不会反映在另一个进程中。据我所知,地址在机器中是全球唯一的。
我的问题是:为什么相同的地址位置A同时存储不同的值,即使堆被复制了?
答案 0 :(得分:2)
“真实”内存地址与您通常使用的内存地址(即“虚拟”内存地址)之间存在差异。虚拟内存基本上只是操作系统的抽象,以便管理不同的页面,这允许操作系统将页面从RAM切换到HDD(page file),反之亦然。
这允许操作系统即使在达到RAM容量时也能继续运行,并将相关页面文件放入RAM内的随机位置而不改变程序的逻辑(否则,指向0x1234的指针突然指向0x4321之后)页面切换已经发生。)
如果你的进程分叉,基本上只是页面文件的一个副本会发生什么,我认为它允许更智能的算法发生,例如只有在一个进程实际修改页面文件时进行复制。
要提到的一个重要方面是分叉不应该更改任何内存地址,因为(例如在C中)应用程序中可能存在相当多的指针逻辑,依赖于你分配的记忆。如果地址在分叉后突然改变,那么它将破坏该指针逻辑的大部分(如果不是全部的话)。
您可以在此处详细了解:http://en.wikipedia.org/wiki/Virtual_memory或者,如果您真的感兴趣,我建议阅读William Stallings撰写的“操作系统 - 内部和设计原则”,其中应涵盖大部分内容,包括原因和方式使用虚拟内存。在this StackOverflow thread中也有一个很好的答案。最后,您可能还想阅读this,this和this问题的答案。