具体来说,fork()如何在Linux中处理从malloc()dynamic分配的内存?

我有一个父母和孩子的程序。 在fork()之前,父进程调用malloc()并用一些数据填充数组。 在fork()之后,孩子需要这些数据。 我知道我可以使用pipe道,但下面的代码似乎工作:

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int main( int argc, char *argv[] ) { char *array; array = malloc( 20 ); strcpy( array, "Hello" ); switch( fork() ) { case 0: printf( "Child array: %s\n", array ); strcpy( array, "Goodbye" ); printf( "Child array: %s\n", array ); free( array ); break; case -1: printf( "Error with fork()\n" ); break; default: printf( "Parent array: %s\n", array ); sleep(1); printf( "Parent array: %s\n", array ); free( array ); } return 0; } 

输出是:

 Parent array: Hello Child array: Hello Child array: Goodbye Parent array: Hello 

我知道在栈中分配的数据在子节点中是可用的,但似乎在堆中分配的数据也可用于子节点。 同样,孩子不能修改堆栈上的父数据,孩子不能修改堆上的父数据。 所以我假设孩子得到自己的堆栈和堆数据副本。

这在Linux中总是如此吗? 如果是这样的话,哪里是支持这个文件? 我检查了fork()手册页,但没有具体提到堆中dynamic分配的内存。

谢谢

Solutions Collecting From Web of "具体来说,fork()如何在Linux中处理从malloc()dynamic分配的内存?"

分配给进程的每个页面(是一个虚拟内存页面,堆栈或堆)被复制,以便分叉进程能够访问它。

实际上,它并没有在开始时被复制,它被设置为写入时复制(Copy-on-Write),意味着一旦一个进程(父或子)尝试修改一个被复制的页面,这样它们就不会相互伤害,仍然可以从fork()的角度访问所有的数据。

例如,实际的可执行文件被映射到内存中的那些代码页通常是只读的,因此在所有分叉的进程中被重用 – 它们不会被再次复制,因为没有人在那里写入,只读,所以写入时复制永远不会被需要。

更多信息可在这里和这里 。

在一个分支之后,孩子完全独立于父母,但是可以继承父母的某些东西。 在堆的情况下,孩子将在概念上有一个父母堆的副本时分叉。 但是,对孩子地址空间的头部进行修改只会修改孩子的副本(例如通过写入时拷贝)。

至于文档:我注意到,文档通常会声明一切都被复制, 除了等等,等等。

简短的回答是“写的很脏” – 更长的答案是..更长。

但是对于所有的意图和目的 – 在C级安全地假设的工作模型是在fork()之后,两个过程是绝对相同的 – 也就是说,孩子得到100%的精确拷贝 – 在fork()的返回值周围),然后在每一边修改它的内存,堆栈和堆时开始发散。

所以你的结论稍微偏离了 – 孩子从父母复制到自己的空间开始 – 然后修改它 – 看到它被修改 – 而父母继续自己的副本。

事实上事情有点复杂 – 因为它试图通过做一些肮脏的事情来避免一个完整的副本; 避免复制,直到它必须。

DW。