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
posted @ 2023-05-17 18:43  言叶以上  阅读(44)  评论(0编辑  收藏  举报