微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用waitpid还是sigaction?

我明白了:
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,0); print value returned from this waitpid - it is -1
}

感谢有人帮助我理解这一点.

解决方法

如果你的目的是运行子进程,做一些事情,然后等待它完成,你真的不需要处理SIGCHLD.在这种情况下,您只需在准备好同步时调用waitpid. SIGCHLD唯一有用的是子终止的异步通知,例如,如果您有一个交互式(或长时间运行的守护程序)应用程序,它会生成各种子项并需要知道它们何时完成.但是,SIGCHLD也非常糟糕/丑陋,因为如果您使用创建子进程的库代码,您可能会捕获库的子进程终止的事件并干扰它们的处理.信号处理程序本质上是进程全局的并且处理全局状态,通常是坏事(tm).

当您有子进程异步终止时,有两种更好的方法

方法1(选择/轮询基于事件):确保您有一个管道往/来自您创建的每个子进程.它可以是他们的stdin / stdout / stderr,也可以只是一个额外的虚拟fd.子进程终止时,管道的末尾将关闭,主事件循环将检测该文件描述符上的活动.从它关闭的事实,你认识到子进程死了,并调用waitpid来收获僵尸.

方法2(基于线程):对于您创建的每个子进程,还要创建一个线程,该线程将立即在子进程的pid上调用waitpid.当waitpid成功返回时,使用您喜欢的线程同步原语让程序的其余部分知道子进程终止,或者只是在终止之前处理此服务器线程中您需要做的所有事情.

这两种方法都是模块化和库友好的(它们可以避免干扰代码或库代码的任何其他部分,这些部分可能正在利用子进程).

原文地址:https://www.jb51.cc/c/120081.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐