Vin*_*Vin 7 c linux operating-system
我已经理解:1)waitpid用于等待孩子的死亡,然后收集SIGCHLD和孩子的退出状态等.2)当我们有一个SIGCHLD的信号处理程序时,我们做了一些与清理相关的事情.孩子或其他东西(由程序员决定)然后做一个waitpid,这样孩子就不会去僵尸然后回来.
现在,当我们执行fork/exec并且子进程返回时,我们是否需要在程序中同时使用1和2?如果我们两者都有,则首先获取SIGCHLD,因此首先调用信号处理程序,因此成功调用其waitpid而不是父进程代码中的waitpid,如下所示:
my_signal_handler_for_sigchld
{
do something
tmp = waitpid(-1,NULL,0);
print tmp (which is the correct value of the child pid)
}
int main ()
{
sigaction(SIGCHLD, my_signal_handler_for_sigchld)
fork()
if (child) //do something, return
if parent // waitpid(child_pid, NULL,0); print value returned from this waitpid - it is -1
}
Run Code Online (Sandbox Code Playgroud)
感谢有人帮助我理解这一点.
R..*_*R.. 19
SIGCHLD如果你的意图是运行子进程,做一些事情,然后等待它完成,你真的不需要处理.在这种情况下,您只需waitpid在准备好同步时调用.唯一SIGCHLD有用的是子终止的异步通知,例如,如果你有一个交互式(或长时间运行的守护进程)应用程序,它会产生各种孩子并需要知道他们何时完成.但是,SIGCHLD对于此目的来说真的很糟糕/丑陋,因为如果您使用创建子进程的库代码,您可能会捕获库的子进程终止的事件并干扰它们的处理.信号处理程序本质上是进程全局的并且处理全局状态,这通常是坏事(tm).
当您有子进程异步终止时,有两种更好的方法:
方法1(基于select/ poll事件):确保您有一个管道往/来自您创建的每个子进程.它可以是他们的stdin/stdout/stderr,也可以只是一个额外的虚拟fd.子进程终止时,管道的末尾将关闭,主事件循环将检测该文件描述符上的活动.从它关闭的事实,你认识到儿童过程已经死亡,并呼吁waitpid收获僵尸.
方法2(基于线程):对于您创建的每个子进程,还要创建一个立即调用waitpid子进程的pid 的线程.当waitpid成功返回时,使用您喜欢的线程同步原语让程序的其余部分知道子进程终止,或者只是在终止之前处理此服务器线程中您需要做的所有事情.
这两种方法都是模块化和库友好的(它们可以避免干扰代码或库代码的任何其他部分,这些部分可能正在利用子进程).