【问题标题】:Does fork() create a duplicate instance of all the variables and object created by the parent process for the child process?fork() 是否为子进程创建父进程创建的所有变量和对象的重复实例?
【发布时间】:2012-10-28 12:35:56
【问题描述】:

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

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

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

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...
}

谁能解释我如何做到这一点??

【问题讨论】:

标签: c multithreading fork


【解决方案1】:

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

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

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

请参阅此链接以了解如何使用:How to share memory between process fork()?

【讨论】:

    【解决方案2】:

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

    COW 是使fork 的一种常见用法(在孩子中紧跟着exec)高效的原因。子进程实际上从不使用从父进程继承的大部分内存空间。

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

    【讨论】:

      【解决方案3】:

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

      仅当子进程试图修改此内存空间时,它才复制给定父内存页。它可以减少fork系统调用的开销。

      不复制的一件事是fork的返回值在child中为0,而child中的PID在父亲中。

      【讨论】:

        【解决方案4】:

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

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

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

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

        【讨论】:

          【解决方案5】:

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

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

          手册页:

          【讨论】:

            猜你喜欢
            • 2018-08-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-03-15
            • 2016-08-23
            • 2011-10-02
            相关资源
            最近更新 更多