3

假设我有一个主进程正在运行,并且在它的执行过程中它已经初始化了一些指针并创建了一些预定义结构的实例。

现在,如果我分叉这个主进程,是否为指针分配了单独的内存?并且是先前存在的变量的重复实例,为这个新进程创建的数据结构?

作为我的要求的一个例子,考虑 -

struct CKT
{
  ...
}

main()
{
   ...Some computations with the structure and other pointers.....
   pid_t pid = fork();
   if(pid == 0) //child
   {
       ..some more computations with the structure...but I need a 
       ..separate instance of it with all the pointers in it as well..
   }
   else if(pid > 0) // parent
   {
       ..working with the original instance of the structure..
   }
   // merging the child process with the parent...
   // after reading the data of the child processes structure's data... 
   // and considering a few cases...
}

谁能解释我如何实现这一目标?

4

5 回答 5

3

是的。但是,它可能不会立即复制旧进程的内存空间。操作系统将尽可能使用写时复制,在任一进程中第一次修改每个内存页面时复制每个内存页面。

COW 使一种常见的使用fork(不久之后是exec在孩子中)有效。子进程实际上从不使用从父进程继承的大部分内存空间。

新进程中的副本将具有与旧进程中完全相同的数字地址,因此旧进程中的所有指针在新进程中仍然有效并指向新进程的对象。这是虚拟内存的一部分,它允许不同的进程使用相同的指针值来引用不同的物理内存。

于 2012-11-08T10:17:08.220 回答
3

指针和内存内容都将为 fork 子项复制。

对于使用 fork 创建的子进程,所有类型的数据指针、内存、变量都将在单独的内存中重复。并且您不能直接更改指针,也不能直接更改来自进程子进程的内存内容。

但是您可以使用内存共享从子进程更改父进程的变量

请参阅此链接以了解如何操作:如何在进程 fork() 之间共享内存?

于 2012-11-08T10:45:42.450 回答
2

是的,理论上,fork系统调用将复制父堆栈等。实际上,在这种情况下,有一种通用方法,名为copy-on-write

它仅在子进程试图修改此内存空间时复制给定父内存页。它允许降低fork系统调用的成本。

不复制的一件事是孩子的返回值fork:0,父亲的孩子的PID。

于 2012-11-08T10:17:33.923 回答
1

是的,您的分叉进程接收所有私有映射内存的副本(默认内存映射通过malloc, calloc, 堆栈帧, 全局变量)

您的孩子会收到所有打开文件描述符的共享副本。意味着这些文件描述符将保持有效并打开,直到父和子都关闭它们。对这些文件描述符的搜索也是共享的。如果您希望将文件描述符设为子私有,那么您将不得不这样fdreopen做。否则,非常建议在 fork 后立即关闭子项中不需要的所有文件描述符。

您的孩子将收到相同的共享 MAP_SHARED内存映射。这些将继续访问父子之间共享的相同物理内存。shm*这适用于通过调用系列和mmapwith获取的所有共享内存MAP_SHARED

您的孩子将不会收到任何标有MADV_DONTFORKflag via的映射madvise。这些将在孩子身上变得无效。这不是默认行为,除非明确使用,否则您不必担心它。

于 2012-11-08T10:56:56.187 回答
0

通过使用共享内存段,您可能会得到您正在寻找的结果。使用mmap系统调用创建一个共享内存段,并将所有共享结构放在该段中。由于您不能malloc在此段上使用(它由系统调用作为指向整个段的指针返回),您必须手动复制结构,并自己进行共享内存使用跟踪。

也许您可以先在本地分配数据,然后评估它们使用了多少内存,并以正确的大小进行共享内存分配。也可以将共享段重新分配到更大的大小,在这种情况下,您将不得不以某种方式从一端向另一端发出重新分配信号(也许通过使用共享映射指向的第一个整数来存储该值?)。

手册页:

于 2012-11-08T16:17:38.690 回答