【问题标题】:double fork using vfork使用 vfork 的双叉
【发布时间】:2010-04-11 14:09:52
【问题描述】:

你好
我正在编写应该调度其他一些子进程的服务器的一部分。
因为我想在某些进程上等待,而在不等待完成的情况下调度其他进程,所以我对第二种进程使用双叉(从而避免僵尸进程)。
问题是,我的服务器拥有大量内存,因此分叉需要很长时间(即使是 Linux 中使用的写时复制分叉,它只复制分页表)
我想用 vfork() 替换 fork(),第二个 fork 很容易(因为它只在孩子中调用 execve()),但我找不到任何方法可以替换第一个。
有谁知道我该怎么做?
谢谢!

服务器是linux(RH5U4),用C++编写。

【问题讨论】:

    标签: c++ c linux fork


    【解决方案1】:

    为什么不简单地让新执行的进程自己做另一个分叉呢?这样只有一个小的简单进程会复制它的页表?

    编辑:

    当然,父进程必须执行一个短时间的 wait() 来清除僵尸进程,但是孙子进程可以运行任意长的时间。

    【讨论】:

      【解决方案2】:

      vfork()只能用于fork,然后调用execexit。此外,vfork() 将阻塞父进程,直到子进程调用 _exitexec,这几乎肯定不是您想要的行为。

      原因是vfork() 不会为新进程复制任何数据,包括堆栈。所以一切都是共享的,很容易不小心改变一些父进程无法处理的东西。由于数据是无副本共享的,所以父进程不能和子进程同时继续运行,所以必须等待子进程到_exit或者调用exec所以父进程启动时不再使用数据修改它。

      【讨论】:

      • 谢谢你,肥皂盒。但我正在寻找一种解决方法,它可以让我在不增加 fork() 成本的情况下进行双分叉
      • 那是_exit 不是exit。你绝对不能在vfork之后再打电话给exit
      【解决方案3】:

      我认为你真正想做的是利用 SIGCHLD 并维护一个子进程列表。然后,您可以通过让您的主进程在子进程更改状态时(主要是当他们死亡时)得到通知并基于此对它们执行一些操作来取消双分叉。您还可以跟踪您的任何子进程的完成时间比预期的要长(因为您将它们的创建时间存储在您的列表中),并在它们发疯且永远无法完成时采取行动。

      【讨论】:

        【解决方案4】:

        不要双叉。处理 SIGCHLD 保存errno,调用wait,恢复errno。

        【讨论】:

          【解决方案5】:

          出于类似的原因,我相信您可以使用我提出的另一个问题的答案。你可以vfork() + exec() 到一个再次分叉的可执行文件。见setuid() before calling execv() in vfork() / clone()

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-06-01
            • 1970-01-01
            • 1970-01-01
            • 2015-07-26
            • 1970-01-01
            • 2014-06-15
            • 2014-01-31
            • 2011-09-26
            相关资源
            最近更新 更多