僵尸进程

工作中,一个模块出现了僵尸进程,大致一看应该是system调用引起的。搜了一下僵尸进程的处理。


一、僵屍進程的産生

当子进程比父进程先运行结束,而父进程没有回收子进程的时候,子进程将成为一个僵尸进程。如果父进程先退出,子进程被init接管,子进程退出后init会回收,就没事了。

二、僵屍進程的危害

僵尸进程是一个运行完毕的进程,所有资源都已经释放了,除了它的进程表项。因此,导致的影响如下:如果操作系统最多能管理1000个进程,那么僵尸进程的存在,将会使得操作系统管理正常进程减少。

三、如何避免僵屍進程的産生

1、父进程通过wait和waitpid等函数等待子进程结束,这会导致父进程挂起

2. 如果父进程很忙,那么可以用signal函数为SIGCHLD安装handler,因为子进程结束后,父进程会收到该信号,可以在handler中调用wait回收(没有试验过)

3. 如果父进程不关心子进程什么时候结束,那么可以用signal(SIGCHLD, SIG_IGN)通知内核,自己对子进程的结束不感兴趣,那么子进程结束后,内核会回收,并不再给父进程发送信号

4. 还有一些技巧,就是fork两次,父进程fork一个子进程,然后继续工作,子进程fork一个孙进程后退出,那么孙进程被init接管,孙进程结束后,init会回收。不过子进程的回收估计还要自己做。


作为daemon,4相对简单一些,是较为常用的做法;
如果不希望程序自动转后台,3是比较好的方法;


系统中system调用太多,懒得改了。用方法4给封装一下system,到时候替换一下就行了。

int System(const char * cmdstring)
{
    pid_t pid;
    int status;

    if(cmdstring == NULL){

        return (1);
    }


    if((pid = vfork())<0){
        status = -1;
    }
    else if(pid == 0){
        //printf("process forked. pid=%d ppid=%d\n", getpid(), getppid());
        
        pid_t cpid;
        if ((cpid = vfork()) < 0) {
            _exit(127);
        } else if (cpid == 0) {
            //printf("process forked. pid=%d ppid=%d\n", getpid(), getppid());
            execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
            _exit(127); //子进程正常执行则不会执行此语句
        } else {
            //printf("after fork a process, Process[%d] exit.\n", getpid());
            exit(0);
        }
    }
    else{         
        while(waitpid(pid, &status, 0) < 0){
            if(errno != EINTR){
                status = -1;
                break;
            }
        }
        //printf("###################child %d exit###################\n", pid);

    }

    return status;
}


急着版本发布,有问题了再修改吧。先修改了再说吧

(3更简单)



评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值