当前位置:首页 > 系统教程 > 正文

Linux进程控制(二):进程等待(wait/waitpid)与子进程获取(status)

Linux进程控制(二):进程等待(wait/waitpid)与子进程获取(status)

在Linux系统编程中,进程等待是一个至关重要的概念。当父进程创建子进程后,通常需要知道子进程的运行结果,并回收其资源,避免僵尸进程的产生。本文将详细讲解wait函数waitpid函数的使用,以及如何通过子进程状态获取退出信息,帮助小白彻底掌握进程等待的核心知识。

Linux进程控制(二):进程等待(wait/waitpid)与子进程获取(status) 进程等待 wait函数 waitpid函数 子进程状态 第1张

一、为什么需要进程等待?

当子进程退出时,内核会保留其部分数据结构(如退出状态、运行时间等),直到父进程来获取这些信息。如果父进程一直不获取,子进程就会变成僵尸进程,占用系统资源。进程等待的主要目的就是:

  • 回收子进程资源,释放PCB(进程控制块)
  • 获取子进程的退出状态,了解其执行结果
  • 保证父进程在子进程之后结束,避免孤儿进程

二、wait函数详解

wait函数是进程等待的基础函数,原型如下:

    #include pid_t wait(int *status);  

参数status是一个整型指针,用于存储子进程的退出状态。如果不需要状态,可以传入NULL。返回值:成功返回子进程的PID,失败返回-1。wait函数会阻塞父进程,直到任意一个子进程退出。

示例:使用wait回收子进程

    #include #include #include #include int main() {    pid_t pid = fork();    if (pid == 0) {        // 子进程        printf("子进程运行中,PID: %d", getpid());        sleep(2);        exit(42); // 子进程退出,状态码42    } else if (pid > 0) {        // 父进程        int status;        pid_t ret = wait(&status); // 阻塞等待子进程        if (WIFEXITED(status)) {            printf("子进程正常退出,状态码: %d", WEXITSTATUS(status));        }        printf("父进程回收子进程,PID: %d", ret);    }    return 0;}  

三、waitpid函数详解

waitpid函数比wait更灵活,可以指定等待哪个子进程,并支持非阻塞模式。原型:

    pid_t waitpid(pid_t pid, int *status, int options);  
  • pid:可以指定要等待的子进程PID,或使用特殊值:- pid > 0:等待特定PID的子进程- pid = -1:等待任意子进程(同wait)- pid = 0:等待与父进程同组的任意子进程- pid < -1:等待进程组ID为|pid|的任意子进程
  • status:同wait的status参数
  • options:常用选项WNOHANG,表示如果没有子进程退出则立即返回0,不阻塞。

返回值:正常返回子进程PID;如果设置了WNOHANG且没有子进程退出,返回0;出错返回-1。

示例:非阻塞式等待

    #include #include #include int main() {    pid_t pid = fork();    if (pid == 0) {        sleep(5);        exit(0);    } else {        int status;        while (1) {            pid_t ret = waitpid(pid, &status, WNOHANG);            if (ret == 0) {                printf("子进程尚未退出,继续执行其他任务...");                sleep(1);            } else if (ret > 0) {                printf("子进程已退出,PID: %d", ret);                break;            } else {                perror("waitpid");                break;            }        }    }    return 0;}  

四、获取子进程状态(status)

子进程状态通过status参数返回,它是一个整型,包含多种信息。解析status需要使用以下宏:

  • WIFEXITED(status):如果子进程正常退出(调用exit或return),返回真。
  • WEXITSTATUS(status):获取子进程的退出状态码(仅当WIFEXITED为真时有效)。
  • WIFSIGNALED(status):如果子进程因信号而终止,返回真。
  • WTERMSIG(status):获取导致子进程终止的信号编号。
  • WIFSTOPPED(status):如果子进程处于暂停状态(如收到SIGSTOP),返回真(需配合WUNTRACED选项)。
  • WSTOPSIG(status):获取导致子进程暂停的信号编号。

示例代码中已展示了WIFEXITEDWEXITSTATUS的使用。下面是一个完整获取各种状态的示例:

    #include #include #include #include #include int main() {    pid_t pid = fork();    if (pid == 0) {        // 子进程:触发段错误(收到SIGSEGV)        int *p = NULL;        *p = 10;        exit(0);    } else {        int status;        wait(&status);        if (WIFEXITED(status)) {            printf("正常退出,状态码: %d", WEXITSTATUS(status));        } else if (WIFSIGNALED(status)) {            printf("被信号终止,信号: %d", WTERMSIG(status));        } else if (WIFSTOPPED(status)) {            printf("被暂停,信号: %d", WSTOPSIG(status));        }    }    return 0;}  

五、总结

本文详细介绍了Linux中的进程等待机制,重点讲解了wait函数waitpid函数的使用,以及如何通过status宏解析子进程状态。掌握这些知识,可以有效避免僵尸进程,实现父子进程的同步。希望小白读者能通过示例代码亲手实践,加深理解。

(完)