文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>避免fork()产生僵尸进程

避免fork()产生僵尸进程

时间:2010-10-21  来源:bruclan

使用fork创建进程非常实用,但如果对子进程的情况不了解,也可能会产生些副作用。当子进程终止时,它与父进程之间的关联还会继续保持,直到父进程结束或者调用wait。这样一来,进程表中代表子进程的表项就不会立刻释放。虽然子进程已经结束,但是它仍然在系统中存在着,这是因为父进程还需要在调用wait时使用子进程的退出码。此时,子进程就成为了僵尸(zombie)进程。

举一个会产生僵尸进程的例子:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    pid_t pid;
    char* message;
    int n;
   
    printf("fork program starting\n");
    pid = fork();
    switch(pid) {
        case -1:
            perror("fork failed\n");
            exit(1);
        case 0:
            message = "This is the child";
            n = 3;
            break;
        default:
            message = "This is the parent";
            n = 60;
            break;
    }
    for(; n>0; n--) {
        puts(message);
        sleep(1);
    }
   
    exit(0);
}

如上所示,子进程输出消息的次数只有3次,3次过后,子进程就完成了自己的任务,该结束了。但是由于父进程还没有完成自己的任务,不能退出,此时的子进程就成为了僵尸进程。

如果父进程异常终止,那么子进程就会被init进程(pid=1)接管,它的父进程就会变为init进程。僵尸进程将一直保存在进程表中,直到被init进程发现并释放。进程表越大,这一过程就越慢。应该尽量避免僵尸进程的产生,因为在被释放之前,它们会一直占用系统资源。

如何避免僵尸进程的产生呢?可以使用waitpid函数。先来看看该函数的声明:
#include <sys/types.h>
#include <sys/wait.h>

pid_t waitpid(pid_t pid, int* stat_loc, int options);

pid:需要等待的子进程的pid;如果为-1,表示waitpid将返回任一子进程的信息。
stat_loc:接收子进程的状态信息。
options:控制waitpid行为的选项。常用的一个值为WNOHANG,它可以防止waitpid将调用者挂起。可以用这个选项来判断是否有子进程已经结束,如果没有,程序将继续运行。

如果子进程没有结束或意外终止,该函数返回0,否则返回子进程pid。如果返回-1表示waitpid调用失败并设置errno。

举个例子:
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    pid_t pid;
    char* message;
    int n;
    int exit_code;
   
    printf("fork program starting\n");
    pid = fork();
    switch(pid) {
        case -1:
            perror("fork failed\n");
            exit(-1);
        case 0:
            message = "This is the child";
            n = 20;
            exit_code = 37;
            break;
        default:
            message = "This is the parent";
            n = 3;
            exit_code = 0;
            break;
    }
    for(; n>0; n--) {
        puts(message);
        sleep(1);
    }
    if(pid != 0) {
        pid_t child_pid;
        int stat_val;
        while(1) {
            child_pid = waitpid(-1, &stat_val, WNOHANG);
            if(child_pid) {
                printf("Child process (%d) has finished", child_pid);
                if(WIFEXITED(stat_val)) {
                    printf(", exit code %d.\n", WEXITSTATUS(stat_val));
                }
                else {
                    printf(" abnormally.\n");
                }
                break;
            }
            printf("Child process is running\n");
            sleep(1);
        }
    }
   
    exit(exit_code);
}

这里在一个while(1)循环中不停地检测子进程是否终止,如果停止则退出循环。
相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载