前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >wait() 回收子进程

wait() 回收子进程

作者头像
我与梦想有个约会
发布2023-10-20 17:44:59
1800
发布2023-10-20 17:44:59
举报
文章被收录于专栏:jiajia_dengjiajia_deng

在前面的文章中我们讨论了如何通过 fork() 函数创建子进程,创建后的子进程如果优先于父进程退出,子进程的虚拟内存空间就消失了,但是进程控制块PCB并没有消失,这里面包含了这个子进程的退出状态,需要由父进程来进行回收。在父进程回收之前,这个进程被称为僵尸进程(僵死进程),任何一个子进程都会经过这段僵尸进程的阶段,最后由父进程来回收。

子进程退出有两种情况,一种是程序正常退出了,比如exit(1)或者main函数返回等。而另外一种则是非正常退出,一般情况下是收到了某种信号,比如“kill -9”。正常退出的情况下,我们要获取进程退出的代码,而非正常退出的状态下我们要获取到底进程因为哪中信号而终止了。 我们首先来看一个最简单的 wait 函数的应用:

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char* argv[])
{
    pid_t pid, wpid;

    pid = fork();

    if (pid  == -1)
    {
        perror("fork error");
        exit(1);
    }
    else if (pid == 0)
    {
        printf("I'm child, PID = %d\n", getpid());
        // 子进程等待5秒
        sleep(5);
    }
    else if (pid > 0)
    {
        // 父进程调用wait函数处于阻塞状态,直到子进程结束wait才会返回
        wpid = wait(NULL);
        if (wpid == -1)
        {
            perror("wait error");
        }
        printf("I'm parent, I catched child process, PID = %d\n", wpid);
    }
    return 0;
}

上面代码是一个最简单的 wait() 的应用了,这样的 wait() 只起到了回收子进程 PCB 的作用,而并没有对子进程的退出消息做任何的接收或处理。下面的代码演示了如何对子进程的退出情况做出响应。

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main(int argc, char* argv[])
{
    pid_t pid;
    pid = fork();
    if (pid == -1)
    {
        perror("fork error");
        exit(1);
    }
    else if (pid == 0)
    {
        printf("I'm child, PID = %d\n", getpid());
        sleep(1);
    }
    else if (pid > 0)
    {
        int status;
        int wpid;
        wpid = wait(&status);
        // 子进程正常退出判断,如果返回真则证明子进程是正常退出的
        if (WIFEXITED(status))
        {
            // 打印已经退出的子进程的 pid
            printf("I'm parent, The child process %d exit normally\n", wpid);
            // 打印子进程程序退出后的返回值
            printf("return value : %d\n", WEXITSTATUS(status));
        }
        // 如果子进程是非正常退出,那么一定是接收到某信号,下面就是判断是否是接收到了信号
        else if (WIFSIGNALED(status))
        {
            // 获取进程是接收到了什么信号导致非正常退出的
            printf("Child terminated abnormally, signal %d\n", WTERMSIG(status));
        }
    }
    return 0;
}

从上面的例子中可以看出,WIFEXITED是用来判断子进程的退出状态的,如果返回真则证明子进程是正常退出的,随后使用了WEXITSTATUS获取了退出代码。而WIFSIGNALED则是判断子进程是否是接收到了某个信号,如果是收到了某个信号证明进程是非正常退出的,那么使用WTERMSIG获取收到的信号。可通过 kill -l 查看信号编号的对应内容。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015-06-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档