Linux多进程19-SIGCHLD 信号
SIGCHLD信号产生的条件
- 子进程终止时
- 子进程接收到 SIGSTOP 信号停止时
- 子进程处在停止态,接受到SIGCONT后唤醒时
以上三种条件都会给父进程发送 SIGCHLD 信号,父进程默认会忽略该信号
父进程捕捉到SIGCHLD信号时调用wait, waitpid回收子进程资源, 解决僵尸进程问题
sigchld.c
/*
使用SIGCHLD信号解决僵尸进程的问题
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <sys/wait.h>
void myFun(int num)
{
printf("捕捉到的信号:%d\n", num);
//回收子进程PCB资源
// while (1)
// {
// wait(NULL);
// }
while (1)
{
int ret = waitpid(-1, NULL, WNOHANG); //非阻塞
if (ret > 0)
{
printf("child die, pid=%d\n", ret);
}
else if (ret == 0)
{
//说明还有子进程活着
break;
}
else if (ret == -1)
{
//没有子进程
break;
}
}
}
int main(int argc, char const *argv[])
{
//提前设置好阻塞信号集, 阻塞SIGCHLD,可能子进程很快结束, 父进程还没有注册完信号捕捉
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGCHLD);
sigprocmask(SIG_BLOCK, &set, NULL);
//创建一些子进程
pid_t pid;
for (int i = 0; i < 20; i++)
{
pid = fork();
if (pid == 0)
{
break;
}
}
if (pid > 0)
{
//父进程
//捕捉子进程结束时发送的SIGCHLD信号
struct sigaction act;
act.sa_flags = 0;
act.sa_handler = myFun;
sigemptyset(&act.sa_mask);
sigaction(SIGCHLD, &act, NULL);
//注册完信号捕捉后解除阻塞
sigprocmask(SIG_UNBLOCK, &set, NULL);
while (1)
{
printf("parent process pid: %d\n", getpid());
sleep(2);
}
}
else if (pid == 0)
{
printf("child process pid: %d\n", getpid());
}
return 0;
}
运行程序
$./sigchld
child process pid: 4771
child process pid: 4782
child process pid: 4772
child process pid: 4773
child process pid: 4776
child process pid: 4778
child process pid: 4777
child process pid: 4779
child process pid: 4783
child process pid: 4784
child process pid: 4787
child process pid: 4788
child process pid: 4781
child process pid: 4780
parent process pid: 4770
捕捉到的信号:17
child process pid: 4790
child process pid: 4786
child process pid: 4789
child process pid: 4775
child die, pid=4771
child die, pid=4772
child die, pid=4773
child die, pid=4776
child die, pid=4777
child die, pid=4778
child die, pid=4779
child die, pid=4780
child die, pid=4781
child die, pid=4782
child die, pid=4783
child die, pid=4784
child die, pid=4786
child die, pid=4787
child die, pid=4788
child die, pid=4790
捕捉到的信号:17
child process pid: 4774
捕捉到的信号:17
child die, pid=4774
child die, pid=4775
child die, pid=4789
parent process pid: 4770
child process pid: 4785
捕捉到的信号:17
child die, pid=4785
parent process pid: 4770
parent process pid: 4770
parent process pid: 4770
parent process pid: 4770
parent process pid: 4770
parent process pid: 4770
parent process pid: 4770
parent process pid: 4770
parent process pid: 4770
parent process pid: 4770
parent process pid: 4770
parent process pid: 4770
^C