如何编程解决僵尸进程的问题?

消除僵尸进程涉及到以下两个小问题。

1、如何使用SIGCHLD信号解决僵尸进程?

        利用sigaction函数捕捉SIGCHLD信号,执行包含waitpid函数的回调函数。

2、子进程很快就结束,父进程还没有注册完信号捕捉,就会有多个子进程结束,发出多个信号,由于未决信号集只能记录一个信号,其余的被忽视。导致不能杀死所有的僵尸进程。

       下面是具体的编程。

/*
    SIGCHLD信号产生的条件
        1、子进程结束
        2、子进程暂停
        3、子进程继续运行
        都会给父进程发送该信号,父进程默认忽略该信号

    使用SIGCHLFD解决僵尸进程问题。


*/
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<stdio.h>
#include<signal.h>
#include<sys/wait.h>

void myFun(int num){
    printf("捕捉到信号%d\n",num);
    // 回收子进程资源
    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()
{
    // 设置阻塞信号集,阻塞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。        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
31. 在Linux系统下,发送信号的命令是kill。在C语言中,可以使用kill函数来发送信号。 32. pid_t fork() 的返回值为新进程的进程ID,如果返回值为0,则表示当前进程为子进程;如果返回值大于0,则表示当前进程为父进程,返回值即为子进程的进程ID;如果返回值为-1,则表示创建子进程失败。 33. 系统调用是通过操作系统提供的接口直接调用内核功能的一种编程方式,而库函数则是在用户空间中运行的函数库,通过调用库函数来实现对系统功能的访问。 34. C/S架构指的是客户端/服务器架构,其中客户端和服务器通过网络进行通信,客户端向服务器发起请求,服务器处理请求并返回结果给客户端。 35. sprintf函数是C语言中的字符串格式化函数,用于将格式化后的字符串输出到指定的缓冲区中。 36. 进程的创建可以通过fork函数来实现,进程间通信的机制包括管道、共享内存、消息队列、信号量等。 37. 线程的创建可以通过pthread_create函数来实现,线程间通信的机制包括互斥锁、条件变量、信号量等。 38. 如果a可能为负数,则应该定义为有符号类型。 39. 可以使用wait或waitpid函数来让父进程等待子进程结束并获取子进程的退出状态。 40. 使用管道和共享内存时,需要先创建相应的管道或共享内存,然后通过读写操作来进行进程间通信。 41. 进程关闭后,管道或共享内存仍然存在,但是不能再进行读写操作。 42. 僵尸进程是指已经结束但是父进程还没有处理其退出状态的进程。在父进程没有使用wait或waitpid等函数来处理子进程退出状态时,子进程就会变成僵尸进程。 43. 解决僵尸进程的方法包括使用wait或waitpid函数等待子进程退出并获取其退出状态,或者使用信号处理函数来处理SIGCHLD信号。 44. 进程是系统中正在运行的程序的实例,拥有独立的内存空间和资源。线程是进程中的执行单元,多个线程共享同一进程的资源,可以提高程序的并发性和效率。 45. 进程间的通信方式包括管道、共享内存、消息队列、信号量等。 46. 同步是指协调多个进程或线程的执行顺序,保证它们按照一定的顺序执行。互斥是指在同一时间只有一个进程或线程可以访问共享资源,其他进程或线程需要等待该进程或线程释放资源后才能访问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@Finish_all

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值