Chinaunix首页 | 论坛 | 博客
  • 博客访问: 49846
  • 博文数量: 9
  • 博客积分: 411
  • 博客等级: 一等列兵
  • 技术积分: 113
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-07 15:32
文章分类

全部博文(9)

文章存档

2010年(9)

我的朋友

分类: C/C++

2010-10-21 16:00:58

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

举一个会产生僵尸进程的例子:
#include
#include
#include
#include

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
#include

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
#include
#include
#include
#include

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)循环中不停地检测子进程是否终止,如果停止则退出循环。
阅读(2537) | 评论(2) | 转发(0) |
0

上一篇:svn cleanup时遇到错误

下一篇:没有了

给主人留下些什么吧!~~

chinaunix网友2010-10-22 14:43:40

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com

chinaunix网友2010-10-22 14:43:26

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com