linux下避免僵尸进程的几种方法

    linux下我们可以调用fork函数创建子进程,创建的子进程将会得到父进程的数据空间、堆、栈......副本(采用写时复制机制),子进程将会继承父进程的信号掩码、信号处理方式、当前工作目录、会话id、组id......。当子进程退出时父进程应当及时获取子进程退出状态,否则,如果父进程是一直在运行,那么子进程的退出状态将一直保存在内存中,直到父进程退出才释放。

我们可以使用如下几种方法避免僵尸进程的产生:
    1.在fork后调用wait/waitpid函数取得子进程退出状态。

    2.调用fork两次(第一次调用产生一个子进程,第二次调用fork是在第一个子进
      程中调用,同时将父进程退出(第一个子进程退出),此时的第二个子进程的父
      进程id为init进程id(注意:新版本Ubuntu并不是init的进程id))。

    3.在程序中显示忽略SIGCHLD信号(子进程退出时会产生一个SIGCHLD信号,我
      们显示忽略此信号即可)。

    4.捕获SIGCHLD信号并在捕获程序中调用wait/waitpid函数。
方法一:

#include "../common/common.h"

int main(void)
{
    pid_t pid;

    if ((pid = fork()) < 0) {
        perror("fork error");
        return EXIT_FAILURE;
    } else if (0 == pid) {
        printf("[%ld] child process is running...\n", (long)getpid());
        _exit(0);
    }

    //sleep(15);

    if (waitpid(pid, NULL, 0) < 0) {
        perror("waitpid error");
        return EXIT_FAILURE;
    }

    for (; ;) {
        pause();
    }
    return EXIT_SUCCESS;
}
方法二:

#include <sys/wait.h>

#include "../common/common.h"

int main(void)
{
    pid_t pid;

    if ((pid = fork()) < 0) {
        perror("fork error");
        return EXIT_FAILURE;
    } else if (0 == pid) {
        printf("first child is running..\n"); 
        /**在第一个子进程中再次fork***/
        if ((pid = fork()) < 0) {
            perror("fork error");
            return EXIT_FAILURE;
        } else if (pid > 0) {/**父进程退出**/
            printf("[%ld] first child is exit...\n", (long)getpid());
            _exit(0);
        }

        sleep(2);/**确保父进程先运行**/
        printf("second process pid: %ld, second process's parent pid: %ld\n", (long)getpid(), (long)getppid()); 
        //sleep(15);
        printf("[%ld] is exit..\n", (long)getpid());
        _exit(0);
    }

    /***获得第一个子进程的退出状态***/
    if (waitpid(pid, NULL, 0) < 0) {
        perror("waitpid error");
        return EXIT_FAILURE;
    }

    for(;;)
        pause();

    return EXIT_SUCCESS;
}
方法三:

#include <signal.h>

#include "../common/common.h"

int main(void)
{
    /***显示忽略SIGCHLD信号****/
    if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
        perror("signal error");
        return EXIT_SUCCESS;
    }


    pid_t pid;
    int i;
    /**产生10个子进程***/
    for (i=0; i<10; ++i) {
        if ((pid = fork()) < 0) {
            perror("fork error");
            return EXIT_FAILURE;
        } else if (0 == pid) {
            _exit(0);
        }

        sleep(2);
        continue;
    }


    for (; ;)
        pause();

    return EXIT_SUCCESS;
}
方法四:

#include <signal.h>
#include <sys/wait.h>

#include "../common/common.h"


void sig_chld(int signo);

int main(void)
{
    /**捕获此信号, 此刻系统会立刻检测是否有次信号产生**/
    if (signal(SIGCHLD, sig_chld) == SIG_ERR) {
        handler_err("signal error to SIGCHLD");
    }

    pid_t pid;
    int i;


    for (i=0; i<10; i++) {

        if ((pid = fork()) < 0) {
            handler_err("fork error");
        } else if (0 == pid) {
            printf("child pid: %d\n", getpid());
            _exit(0);
        } 

        sleep(1);
        continue;
    }

    for (; ;) {
        pause();
    }   
    return EXIT_SUCCESS;
}

/**捕获到信号后会立刻执行此段代码***/
void sig_chld(int signo)
{
    printf("receive child signal\n");


    if (waitpid(-1, NULL, 0) < 0) {
        perror("waitpid error");
    }

    if (signal(SIGCHLD, sig_chld) == SIG_ERR) {
        perror("signal error to SIGCHLD");
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值