SIGCHLD信号与进程异步等待


进程等待


首先,让我们先来回顾一下有关进程等待的知识。

所谓进程等待,说的就是父进程等待子进程:

2

如图,父进程调用wait和waitpid函数等待子进程,从而清理系统中的僵尸进程。在此过程中,父进程可以阻塞等待子进程结束,也可以非阻塞地查询是否有子进程结束等待清理(也就是轮询的方式)

若采用阻塞等待方式,父进程就不能处理自己的工作了;采用非阻塞方式,父进程在处理自己工作的同时还要时不时地轮询⼀下子进程状态,程序实现复杂。


SIGCHLD信号


SIGCHLD是linux系统信号列表中定义的第17号信号:

1

事实上,进程等待不只是上面描述的那样,子进程在终止时会给父进程发SIGCHLD信号,因为⼦进程终止是一个异步事件,所以发生这种信号也是内核向父进程发的异步通知。而大多数父进程对该信号的默认处理动作是忽略。

尽管如此,父进程还是可以自定义SIGCHLD信号的处理函数,这样它只需专心处理自己的工作,而不必关⼼子进程了, 子进程终止时会通知父进程,父进程在信号处理函数中调用wait清理子进程即可。


Code


有了进程等待和SIGCHLD信号的概念,接下来利用SIGCHLD信号编写代码实现父进程对子进程的异步等待

1.验证子进程退出时会给父进程发送SIGCHLD信号的机制

代码:先创建子进程,然后使其直接退出。再让父进程调用waitpid和signal函数等待子进程并捕捉子进程发送的17号信号

3

运行结果:

4

结果表明,父进程id为14924的进程确实受到了其子进程退出时发送的17号信号。

2.编写父进程等待子进程的异步版本

上边父进程在等待子进程成功后直接退出,现在我们要实现父进程等待子进程成功后,继续做自己的事情。这就是异步等待。

代码:
在捕捉函数里加入while循环,使得在程序中有多个子进程时,父进程就会一直等待所有子进程退出(id > 0)

5

先让父进程运行,5秒之后子进程退出。父进程等待成功后,继续做自己的事情。

6

运行结果:

7

可以看出,情况如预料的那样。实现了父进程对子进程的异步等待。

但这里有一个问题,如果有子进程一直不退出,那么父进程就会一直阻塞等待。这显然是我们不愿看到的。所以为了解决这个问题,对捕捉函数handler修改如下:

8

在上面的代码中,对waitpid函数的宏参数WNOHANG进行设置,实现非阻塞等待。0和-1都是其可能的返回值,返回0表示没有子进程可以等,返回-1表示函数调用失败。这样就避免了父进程的阻塞等待。所以在while循环里再加入了switch选择分支结构。增强代码的健壮性。

再次运行程序,结果依然无误:

9


The End


关于linux中的信号,以后也会有博文介绍,敬请期待。。。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值