Linux使用waitpid回收多个子进程的方法小结

 更新时间:2025年11月10日 09:43:22   作者:郝学胜-神的一滴  
在Unix/Linux系统中,创建子进程后,父进程需要负责回收这些子进程的资源,否则会导致"僵尸进程"的产生,本文将详细介绍如何使用waitpid系统调用有效地回收多个子进程,需要的朋友可以参考下

什么是waitpid

waitpid是Unix/Linux系统提供的一个系统调用,用于等待子进程的状态改变并回收其资源。相比于wait函数,waitpid提供了更灵活的控制选项,可以指定等待哪个特定的子进程,以及是否阻塞等待【1†source】。

#include <sys/wait.h>

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

参数说明:

pid: 要等待的子进程ID。特殊值包括:

  • -1: 等待任意子进程
  • 0: 等待与调用进程同组的任意子进程

0: 等待指定PID的子进程

  • status: 用于存储子进程退出状态的指针
  • options: 控制选项,最常用的是WNOHANG,表示非阻塞模式

回收多个子进程的方法

方法一:循环调用waitpid

最简单的方法是在父进程中循环调用waitpid,直到所有子进程都被回收:

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>

int main() {
    pid_t pids[5];
    int i;
    
    // 创建5个子进程
    for (i = 0; i < 5; i++) {
        pids[i] = fork();
        if (pids[i] == 0) {
            // 子进程代码
            printf("Child process %d started\n", getpid());
            sleep(1 + rand() % 3); // 随机休眠1-3秒
            printf("Child process %d exiting\n", getpid());
            exit(0);
        }
    }
    
    // 父进程回收子进程
    int status;
    pid_t pid;
    
    for (i = 0; i < 5; i++) {
        pid = waitpid(pids[i], &status, 0);
        if (pid == -1) {
            perror("waitpid");
            exit(1);
        }
        printf("Parent reaped child %d\n", pid);
    }
    
    return 0;
}

方法二:非阻塞方式回收子进程

使用WNOHANG选项,父进程可以在不阻塞的情况下检查子进程状态:

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>

int main() {
    pid_t pids[5];
    int i;
    
    // 创建5个子进程
    for (i = 0; i < 5; i++) {
        pids[i] = fork();
        if (pids[i] == 0) {
            // 子进程代码
            printf("Child process %d started\n", getpid());
            sleep(1 + rand() % 3); // 随机休眠1-3秒
            printf("Child process %d exiting\n", getpid());
            exit(0);
        }
    }
    
    // 父进程非阻塞方式回收子进程
    int status;
    pid_t pid;
    int children_left = 5;
    
    while (children_left > 0) {
        pid = waitpid(-1, &status, WNOHANG);
        
        if (pid > 0) {
            // 成功回收一个子进程
            printf("Parent reaped child %d\n", pid);
            children_left--;
        } else if (pid == 0) {
            // 有子进程仍在运行
            printf("Waiting for children to finish...\n");
            sleep(1);
        } else {
            // 出错
            perror("waitpid");
            exit(1);
        }
    }
    
    printf("All children have been reaped\n");
    return 0;
}

方法三:信号处理方式回收子进程

可以通过SIGCHLD信号来通知父进程子进程已经终止,然后在信号处理函数中回收子进程:

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdlib.h>

void sigchld_handler(int sig) {
    int status;
    pid_t pid;
    
    // 回收所有已终止的子进程
    while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
        printf("Parent reaped child %d\n", pid);
    }
}

int main() {
    pid_t pids[5];
    int i;
    
    // 设置SIGCHLD信号处理
    struct sigaction sa;
    sa.sa_handler = sigchld_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
    if (sigaction(SIGCHLD, &sa, NULL) == -1) {
        perror("sigaction");
        exit(1);
    }
    
    // 创建5个子进程
    for (i = 0; i < 5; i++) {
        pids[i] = fork();
        if (pids[i] == 0) {
            // 子进程代码
            printf("Child process %d started\n", getpid());
            sleep(1 + rand() % 3); // 随机休眠1-3秒
            printf("Child process %d exiting\n", getpid());
            exit(0);
        }
    }
    
    // 父进程继续执行其他任务
    printf("Parent doing other work...\n");
    sleep(5);
    printf("Parent finished\n");
    
    return 0;
}

最佳实践和注意事项

  1. 及时回收子进程:父进程应该及时回收子进程,避免僵尸进程的产生【2†source】。
  2. 处理异常情况:在调用waitpid时,应该检查返回值,处理可能的错误情况。
  3. 信号处理注意事项:使用信号处理方式回收子进程时,需要注意信号处理函数的可重入性和安全性。
  4. 避免竞争条件:在多线程环境中使用waitpid时,需要注意同步问题,避免竞争条件。
  5. 使用WNOHANG:对于需要同时处理多个任务的父进程,使用WNOHANG选项可以避免阻塞,提高程序的响应性【3†source】。

总结

waitpid是Unix/Linux系统中回收子进程的强大工具,通过合理使用waitpid及其选项,父进程可以有效地管理多个子进程。本文介绍了三种常见的回收多个子进程的方法,包括循环调用、非阻塞方式和信号处理方式,并提供了相应的代码示例。根据具体的应用场景和需求,选择最适合的方法来管理子进程,可以提高程序的健壮性和效率。

在实际开发中,还需要考虑程序的错误处理、资源释放和信号安全等问题,确保程序在各种情况下都能正确运行。

以上就是Linux使用waitpid回收多个子进程的方法小结的详细内容,更多关于Linux waitpid回收多个子进程的资料请关注脚本之家其它相关文章!

相关文章

  • Linux磁盘分区与挂载的完整流程

    Linux磁盘分区与挂载的完整流程

    磁盘管理是 Linux 系统运维的基础,涉及磁盘类型识别、分区方案选择、格式化及挂载等操作,本文将系统讲解不同磁盘类型的表示方法、分区工具的使用、MBR 与 GPT 分区方案的差异,需要的朋友可以参考下
    2025-08-08
  • 在linunx系统中搭建静态文件服务的流程步骤

    在linunx系统中搭建静态文件服务的流程步骤

    在服务器上有一些文件,想共享给其他用户下载,同时因为ftp和sftp被禁用,且使用起来不太方便,需要找一种搭建成本低,安全高效的方式来完成此功能,因此linux上的httpd服务是一个很好的选择,所以本文给大家介绍了在linux系统中搭建静态文件服务的流程步骤
    2024-02-02
  • Linux实现搭建ssh并允许使用root远程

    Linux实现搭建ssh并允许使用root远程

    这篇文章主要介绍了Linux实现搭建ssh并允许使用root远程方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-02-02
  • linux配置SSH全过程

    linux配置SSH全过程

    这篇文章主要介绍了linux配置SSH全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • 在Linux中使用MD5实现用户验证的解决方法

    在Linux中使用MD5实现用户验证的解决方法

    本篇文章小编为大家介绍,在Linux中使用MD5实现用户验证的解决方法。需要的朋友参考下
    2013-04-04
  • apache的commons-pool2原理与使用实践记录

    apache的commons-pool2原理与使用实践记录

    Apache Commons Pool2是一个高效的对象池化框架,通过复用昂贵资源(如数据库连接、线程、网络连接)优化系统性能,这篇文章主要介绍了apache的commons-pool2原理与使用详解,需要的朋友可以参考下
    2025-05-05
  • centos 7 源码安装openssh的方法

    centos 7 源码安装openssh的方法

    这篇文章主要介绍了centos 7 源码安装openssh的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06
  • 使用Apache commons-cli包进行命令行参数解析的示例代码

    使用Apache commons-cli包进行命令行参数解析的示例代码

    Apache的commons-cli包是专门用于解析命令行参数格式的包。这篇文章给大家介绍使用Apache commons-cli包进行命令行参数解析的示例代码,感兴趣的朋友跟随脚本之家小编一起学习吧
    2018-05-05
  • Linux kde中11个你不知道的应用程序

    Linux kde中11个你不知道的应用程序

    今天小编就为大家分享一篇关于Linux kde中11个你不知道的应用程序,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-10-10
  • APACHE 自定义404错误页面设置方法

    APACHE 自定义404错误页面设置方法

    自定义404页面返回不当状态码如200等给网站最终SEO效果带来的不利影响,因此,确保自定义的404错误页面能够返回404状态码是极为重要的,也是网站优化与SEO的基本要求
    2017-03-03

最新评论