2010-04-11 38 views
3


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

服务器是一个用C++编写的linux(RH5U4)。

回答

1

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

原因是vfork()未为新进程创建任何数据(包括堆栈)的任何副本。所以一切都是共享的,并且很容易意外地改变父进程无法处理的东西。由于数据在没有副本的情况下共享,父进程无法与子进程同时继续运行,因此它必须等待子进程_exit或调用exec,以便在父进程开始修改时不再使用数据。

+0

谢谢SoapBox。但我正在寻找一种解决方法,它将允许我在不增加叉子成本的情况下使叉子变成双叉() – 2010-04-11 16:34:55

+1

'_exit'不是'exit'。 'vfork'之后你绝对不能调用'exit'。 – 2011-07-05 04:08:49

2

为什么不简单地让新执行的进程自己做另一个分支呢?那样,只有一个小的简单的过程将其页面表复制?

编辑:

当然的父母将不得不做一个短期的wait()的清理从一个僵尸,但孙子过程可能则只要它想运行。

1

我认为你真正想要做的就是利用SIGCHLD并维护一个子进程列表。然后,您可以通过在儿童改变状态(主要是在他们死亡时)时通知您的主流程并根据该状态对他们执行某些操作来取消双叉。你也可以跟踪你的任何子进程的完成时间比预期的要长(因为你将他们的创建时间存储在你的列表中),并且如果他们发疯并且从未完成就采取行动。

1

不要双叉。处理SIGCHLD以保存errno,呼叫等待,恢复errno。