C语言多进程创建和回收的实现实例

 更新时间:2025年11月11日 09:00:09   作者:yugi987838  
本文主要介绍了C语言多进程中的孤儿进程和僵尸进程的创建及回收方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、多进程创建和回收

  • 孤儿进程:父进程先退出了,子进程没有退出,成为孤儿进程,父进程变成1号进程。
  • 僵尸进程:父进程没有退出,子进程退出了,但是父进程没有回收子进程资源,导致子进程变成僵尸进程。

1. fork()

创建子进程函数,一个进程可以创建多个子进程。

pid_t fork(void)
返回值
    小于0 创建失败
    等于0 是子进程
    大于0 是父进程

示例:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
 
int main()
{
   
    pid_t ret = fork();
    if (ret < 0)
    {
   
        perror("fork error");
        return -1;
    }
    else if (ret > 0)
    {
   
        printf("here is father,pid is [%d], child pid is [%d]\n", getpid(), ret);
        sleep(1);
    }
    else if (ret == 0)
    {
   
        printf("here is child pid is [%d],father is [%d]\n", getpid(), getppid());
    }
 
    return 0;
}

2. wait()

父进程回收子进程,其中分为wait()和waitpid()函数

pid_t wait(int *status);

返回值
    大于0 返回值为回收的进程id
    返回-1 回收失败

参数 status 进程回收状态
    可以使用下面的宏来说明当前的回收状态
    WIFEXITED(wstatus) 如果正常返回,返回true
    WEXITSTATUS(wstatus) 用于输出正常返回的状态 用 %d 格式化输出
 
    WIFSIGNALED(wstatus) 如果被信号杀死,返回true
    WTERMSIG(wstatus) 用于输出被哪个信号杀死 用 %d 格式化输出
 
    WIFSTOPPED(wstatus) 如果子进程停止了,返回true
    WSTOPSIG(wstatus) 用于输出进程停止是由于哪个信号
    WIFCONTINUED(wstatus) 如果进程被信号SIGCONT重启,返回true
 
    WCOREDUMP(wstatus) 如果子进程发生核心转储,返回true

示例:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
 
// pid_t wait(int *status);
 
int main()
{
   
    pid_t ret = fork();
    if (ret < 0)
    {
   
        perror("fork error");
        return -1;
    }
    else if (ret > 0)
    {
   
        int waitstatus;
        printf("here is father,pid is [%d], child pid is [%d]\n", getpid(), ret);
        pid_t waitid = wait(&waitstatus);
        if (waitid == -1)
        {
   
            perror("wait error");
            return -1;
        }
        else if (waitid > 0)
        {
   
            printf("child pid [%d] is over\n", waitid);
        }
 
        if (WIFEXITED(waitstatus))
        {
   
            printf("exited, status=%d\n", WEXITSTATUS(waitstatus));
        }
        else if (WIFSIGNALED(waitstatus))
        {
   
            printf("killed by signal %d\n", WTERMSIG(waitstatus));
        }
        else if (WIFSTOPPED(waitstatus))
        {
   
            printf("stopped by signal %d\n", WSTOPSIG(waitstatus));
        }
        else if (WIFCONTINUED(waitstatus))
        {
   
            printf("continued\n");
        }
    }
    else if (ret == 0)
    {
   
        printf("here is child pid is [%d],father is [%d]\n", getpid(), getppid());
    }
 
    return 0;
}
 
//输出
here is father,pid is [24290], child pid is [24291]
here is child pid is [24291],father is [24290]
child pid [24291] is over
exited, status=0

3. waitpid()

waitpid中的第三个参数可以让回收进程变成非阻塞的。

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

返回值
    大于0 成功,返回的是回收的进程id
    等于0 返回0是因为第三个参数设置为了 WNOHANG ,等待是非阻塞的,并且这个时候没有子进程需要被回收
    小于0 回收失败

参数 pid 进程id
    小于-1 :等待该数字绝对值的所在组所有子进程,例如-21328,则等待21328组内所有子进程
    -1 :等待所有子进程
    0 :等待组ID等于调用进程的组ID的子进程
    大于0 :等待某个子进程
参数 status 进程回收状态
        同wait函数的
参数 options 回收选项
        0 :不添加选项
        WNOHANG :如果没有子进程需要被回收,就立即返回
        WUNTRACED :如果一个子进程被停止了,就返回
        WCONTINUED :如果一个子进程被SIGCONT从停止转变为运行,就返回

示例:

创建多个子进程并回收它们

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
 
// pid_t waitpid(pid_t pid, int *status, int options);
 
int main()
{
   
    int i = 0;
    for (i = 0; i < 3; i++)
    {
   
        pid_t ret = fork();
        if (ret < 0)
        {
   
            perror("fork error");
            return -1;
        }
        else if (ret > 0)
        {
   
 
            printf("here is father,pid is [%d], child pid is [%d]\n", getpid(), ret);
            // pid_t waitid = wait(&waitstatus);
        }
        else if (ret == 0)
        {
   
            sleep(3);
            printf("here is child [%d] pid is [%d],father is [%d]\n", i, getpid(), getppid());
            break;
        }
    }
 
    if (i == 3)
    {
   
        int waitstatus;
        int num = 0;
        do
        {
   
            pid_t waitid = waitpid(-1, &waitstatus, WNOHANG);
            if (waitid == -1)
            {
   
                perror("wait error");
                return -1;
            }
            else if (waitid > 0)
            {
   
                printf("child pid [%d] is over\n", waitid);
                num++;
            }
            else if (waitid == 0)
            {
   
                // 没有进程被回收,可以做其他事情
                sleep(1);
                continue;
            }
 
            if (WIFEXITED(waitstatus))
            {
   
                printf("[%d] exited, status=%d\n", waitid, WEXITSTATUS(waitstatus));
            }
            else if (WIFSIGNALED(waitstatus))
            {
   
                printf("[%d] killed by signal %d\n", waitid, WTERMSIG(waitstatus));
            }
            else if (WIFSTOPPED(waitstatus))
            {
   
                printf("[%d] stopped by signal %d\n", waitid, WSTOPSIG(waitstatus));
            }
            else if (WIFCONTINUED(waitstatus))
            {
   
                printf("[%d] continued\n", waitid);
            }
 
            if (num == i)
            {
   
                break;
            }
        } while (1);
    }
 
    return 0;
}
//输出
here is father,pid is [24553], child pid is [24554]
here is father,pid is [24553], child pid is [24555]
here is father,pid is [24553], child pid is [24556]
here is child [0] pid is [24554],father is [24553]
here is child [2] pid is [24556],father is [24553]
here is child [1] pid is [24555],father is [24553]
child pid [24554] is over
[24554] exited, status=0
child pid [24555] is over
[24555] exited, status=0
child pid [24556] is over
[24556] exited, status=0

到此这篇关于C语言多进程创建和回收的实现实例的文章就介绍到这了,更多相关C语言多进程创建回收内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 编写C++程序使DirectShow进行视频捕捉

    编写C++程序使DirectShow进行视频捕捉

    这篇文章主要介绍了如何编写C++程序来使DirectShow进行视频捕捉的方法,DirectShow是微软公司在ActiveMovie和Video for Windows的基础上推出的新一代基于COM(Component Object Model)的流媒体处理的开发包,要的朋友可以参考下
    2016-03-03
  • C++实现迷宫算法实例解析

    C++实现迷宫算法实例解析

    这篇文章主要介绍了C++实现迷宫算法实例解析,是一个比较经典的C++算法,有一定的学习与借鉴价值,需要的朋友可以参考下
    2014-07-07
  • opencv实现棋盘格检测

    opencv实现棋盘格检测

    这篇文章主要为大家详细介绍了opencv实现棋盘格检测,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • 在1个Matlab m文件中定义多个函数直接运行的操作方法

    在1个Matlab m文件中定义多个函数直接运行的操作方法

    这篇文章主要介绍了如何在1个Matlab m文件中定义多个函数直接运行,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-12-12
  • C/C++ 获取自身IP与域名片段的示例代码

    C/C++ 获取自身IP与域名片段的示例代码

    这篇文章主要介绍了C/C++ 获取自身IP与域名片段的示例代码,帮助大家更好的理解和学习C/C++编程,感兴趣的朋友可以了解下
    2020-10-10
  • Ubuntu系统下如何在VScode配置OpenCV(C++)环境(.json文件)

    Ubuntu系统下如何在VScode配置OpenCV(C++)环境(.json文件)

    这篇文章主要介绍了如何在VSCode中配置和运行C++程序,包括创建test.cpp文件、配置launch.json、tasks.json和c_cpp_properties.json文件,以及重启VSCode以解决可能的报错问题,需要的朋友可以参考下
    2025-02-02
  • Dev-C++中文乱码问题的解决办法

    Dev-C++中文乱码问题的解决办法

    述Dev-C++是一款非常简洁实用的C/C++集成开发环境,因为高中参加竞赛的原因我也一直有使用它,下面这篇文章主要给大家介绍了关于Dev-C++中文乱码问题的解决办法,需要的朋友可以参考下
    2023-02-02
  • C++超详细讲解函数重载

    C++超详细讲解函数重载

    C++ 允许多个函数拥有相同的名字,只要它们的参数列表不同就可以,这就是函数的重载(Function Overloading),借助重载,一个函数名可以有多种用途
    2022-05-05
  • windows下如何安装OpenCL

    windows下如何安装OpenCL

    这篇文章主要介绍了windows下如何安装OpenCL,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-05-05
  • C++结构体数组实现贪吃蛇

    C++结构体数组实现贪吃蛇

    这篇文章主要为大家详细介绍了C++结构体数组实现贪吃蛇,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03

最新评论