fork()系统调用和进程的内存空间

我引用“当进程使用fork()调用创建一个新进程时,只有父进程和新分叉的子进程之间共享共享内存段。堆栈和堆的副本是为新创建的进程”从Silberschatz的“操作系统概念”解决方案。

但是当我尝试这个程序的时候

#include  #include  #define MAX_COUNT 200 void ChildProcess(void); /* child process prototype */ void ParentProcess(void); /* parent process prototype */ void main(void) { pid_t pid; char * x=(char *)malloc(10); pid = fork(); if (pid == 0) ChildProcess(); else ParentProcess(); printf("the address is %p\n",x); } void ChildProcess(void) { printf(" *** Child process ***\n"); } void ParentProcess(void) { printf("*** Parent*****\n"); } 

结果如下:

 *** Parent***** the address is 0x1370010 *** Child process *** the address is 0x1370010 

父节点和子节点都打印堆中的相同地址。

谁能解释我这里的矛盾。 请清楚说明父母和孩子在内存空间中共享的所有内容。

引用自己的另一个线程。

  • 发出fork()系统调用时,将创建与父进程对应的所有页面的副本,由OS进行子进程加载到单独的内存位置。 但在某些情况下不需要这样做。 考虑一个子进行“exec”系统调用或在fork()之后很快退出的情况。 当需要子进程来执行父进程的命令时,不需要复制父进程的页面,因为exec用要执行的命令替换调用它的进程的地址空间。

    在这种情况下,使用称为写时复制(COW)的技术。 使用此技术,当发生fork时,不会为子进程复制父进程的页面。 相反,页面在子进程和父进程之间共享。 每当进程(父进程或子进程)修改页面时,就会对执行修改的进程(父进程或子进程)单独创建该特定页面的单独副本。 然后,此过程将使用新复制的页面,而不是将来所有引用中的共享页面。 另一个进程(未修改共享页面的进程)继续使用页面的原始副本(现在不再共享)。 这种技术称为写时复制,因为当某个进程写入页面时会复制该页面。

  • 另外,要理解为什么这些程序似乎使用相同的内存空间(事实并非如此),我想引用“操作系统:原理与实践”一书的一部分。

    大多数现代处理器引入了间接级别,称为虚拟地址。 使用虚拟地址,每个进程的内存都从“相同”位置开始,例如,零。 每个过程都认为它拥有整个机器,尽管实际上并非如此。

    所以这些虚拟地址是物理地址的转换,并不代表相同的物理内存空间,留下一个更实际的例子我们可以做一个测试,如果我们编译并运行多次显示静态变量方向的程序,比如这个程序。

     #include  int main() { static int a = 0; printf("%p\n", &a); getchar(); return 0; } 

    如果我们直接处理物理内存,就不可能在两个不同的程序中获得相同的内存地址。

    多次运行程序得到的结果是……

在此处输入图像描述

是的,两个进程对此变量使用相同的地址,但这些地址由不同的进程使用,因此不在同一个虚拟地址空间中 。

这意味着地址相同,但它们并未指向相同的物理内存。 您应该阅读有关虚拟内存的更多信息以了解这一点

您可能正在使用虚拟内存的操作系统上运行程序。 在fork()调用之后,父级和子级具有单独的地址空间,因此地址0x1370010未指向同一位置。 如果一个进程写入*x ,则另一个进程将看不到更改。 (实际上,这些内存可能是相同的内存页面,甚至是交换文件中的相同块,直到它被更改,但操作系统确保在父项或子项写入页面时立即复制页面,所以,只要该程序可以告诉它正在处理自己的副本。)

地址是相同的,但地址空间不是。 每个进程都有自己的地址空间,因此父进程0x1370010与子进程0x1370010不同。

当内核fork()是进程时,复制的内存信息会inheritance相同的地址信息,因为堆是按原样有效复制的。 如果地址不同,您将如何更新自定义结构中的指针? 内核对该信息一无所知,因此这些指针将失效。 因此, 物理地址可能会发生变化(实际上即使在没有fork()情况下,即使在可执行文件的生命周期内也会发生变化,但逻辑地址保持不变。