什么是进程等待?

news2024/11/24 6:04:39

什么是进程等待

在了解进程等待之前,我们要回顾一下什么是僵尸进程:是指一个已经终止执行的进程,但其父进程还没有通过 wait() 系统调用来获取该进程的退出状态信息。当一个进程正常退出或者被终止时,其所占用的系统资源会被操作系统及时回收释放,而其退出状态(退出码)会被传递给其父进程。然而,如果父进程没有合理处理该状态,那么子进程将会变成一个僵尸进程。僵尸进程会占据系统资源,也就是僵尸进程的退出信息等资源,如果不即使清理僵尸进程的话可能会导致进程表被占满,从而导致系统运行缓慢甚至不稳定。

避免僵尸进程的产生:父进程通过调用 wait() 或 waitpid() 系统调用来处理已经终止的子进程,也就是处理僵尸进程所占据的资源信息。

为什么要进行进程等待

  • 解决子进程僵尸问题带来的内存泄漏
  • 我们知道父进程会通过等待子进程,从而接收子进程的退出信息(进程退出码信号编号)而进程退出码标识的就是该进程运行完的退出结果,而信号编号标识的是该进程是什么导致的异常退出。  

怎样等待

 wait方法

wait() 是一个系统调用函数,用于父进程等待子进程的状态改变。它可以用来处理僵尸进程。wait() 函数的作用是:阻塞父进程的执行,直到一个子进程发生状态变化。当子进程终止时,内核会将该进程的退出状态保存在 status 中,并返回该子进程的进程ID(PID)。

pid_t wait(int*status);

返回值:成功则返回被等待进程pid,失败返回-1。

参数:输出型参数,获取子进程退出状态,不关心则可以设置成为NULL
void do_work()
{
    int count=3;
    while(count)
    {
        printf("我是子进程,mypid=%d myppid=%d count=%d\n",getpid(),getppid(),count--);
        sleep(1);
    }
}
int main()
{
    pid_t i=fork();
    if(i==0)//子进程
    {
        do_work();
    }
    else//父进程
    {
        cout<<"等待之前"<<endl;
        pid_t ret=wait(NULL);
        cout<<"等待之后"<<endl;

        if(ret==i)//fork之后父进程会返回子进程的id
        {
            cout<<"等待成功"<<endl;
        }
    }

    return 0;
}

 我们知道fork之后会创建子进程,而且fork后面的代码子进程和父进程都会执行,而父子进程的执行先后顺序取决于调度器的调度,但是我们要知道父进程要接收子进程退出时的资源信息,所以可以明确:进程正常退出时,父进程一定后于子进程退出。而且父进程调用wait的时候会等待子进程执行完。

注意: wait() 函数只能处理直接子进程的状态变化,无法处理所有子进程的退出状态。如果希望处理所有子进程的状态变化,可以使用循环结构来多次调用 wait() 或者使用信号处理机制来实现。

 waitpid方法

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

waitpid() 函数等待成功会返回值为子进程的进程ID

第一个参数 pid 指定需要等待的子进程的进程ID。Pid=-1,等待任意一个子进程。与wait等效。
Pid>0.等待其进程ID与pid相等的子进程。

代替wait使用 

void do_work()
{
    int count=3;
    while(count)
    {
        printf("我是子进程,mypid=%d myppid=%d count=%d\n",getpid(),getppid(),count--);
        sleep(1);
    }
}
int main()
{
    pid_t i=fork();
    if(i==0)//子进程
    {
        do_work();
    }
    else//父进程
    {
        cout<<"等待之前"<<endl;
        pid_t ret=waitpid(-1,NULL,0);//三个参数(等价于wait)
        cout<<"等待之后"<<endl;
        if(ret==i)//父进程会返回子进程的id
        {
            cout<<"等待成功"<<endl;
        }
    }

    return 0;
}

 

第二个参数的使用

参数 status 是一个指向整型变量的指针,用于保存子进程的退出状态信息。
如果不关心子进程的退出状态,可以将 status 设置为 NULL。

wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充。操作系统会根据该参数,将子进程的退出信息反馈给父进程status不能简单的当作整形来看待,可以当作位图来看待,具体细节如下图(只研究status低16比特位):

 我们知道子进程正常退出时会有退出码返回给父进程,而退出码标识该子进程任务的执行情况是否完成。但是子进程不仅仅有正常终止,还有可能会异常终止(收到操作系统发来的信号),所以我们还要接收子进程退出时的信号。所以当我们父进程在等待子进程时会得到两个数字(1.退出码 2.信号码)

 退出码接收

int main()
{
    pid_t i=fork();
    if(i==0)//子进程
    {
        do_work();
        exit(10);
    }
    else//父进程
    {
        cout<<"等待之前"<<endl;
        int sta=0;
        pid_t ret=waitpid(-1,&sta,0);
        cout<<"等待之后"<<endl;
        
        if(ret==i)//父进程会返回子进程的id
        {
            printf("子进程正常退出,pid:%d ,ret:%d ,exit code:%d ,exit sigal:%d \n",getpid(),ret,(sta>>8)&0xFF,sta&0x7F);//这里的&操作符就是得到对应的比特位
        }
    }

    return 0;
}

 退出信号接收

 以上就是所有退出信号而8号对应的就是SIGFPE

第三个参数的认识

options:
WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。
         若正常结束,则返回该子进程的ID。

第三个参数我们一般默认是设为0的,而设为0所代表的含义是阻塞等待,就是父进程会一直等待子进程运行,直到子进程结束之后才开始调用wait函数,从而接收子进程的退出码和信号。但是显然阻塞等待缺陷是:父进程什么操作都干不了,必须等待子进程退出才可以继续执行父进程后续的操作。

而第三个参数为WNOHANG时则意味着非 阻塞等待,也就是说会进行重复的多次调用waitpid函数接口(尽管子进程未退出)。若子进程未退出则waitpid函数返回0,表明还需要继续等待;而返回值大于0则表明返回的是所等待的子进程ID,等待成功且子进程结束;还有返回值小于0的时候则表明等待失败。所以我们非阻塞等待一般会采用循环执行。也称为非阻塞轮询方案。而非阻塞等待相较于阻塞等待的优势就是还可以在进行等待的过程中,父进程可以顺便做一些占据时间不多的事情,而不是像阻塞等待一样一直等待着。

void do_work()
{
    int count=3;
    while(count)
    {
        printf("我是子进程,mypid=%d myppid=%d count=%d\n",getpid(),getppid(),count--);
        sleep(1);
    }
}

int main()//非阻塞等待
{
    pid_t i=fork();//为父进程返回子进程的id,为子进程返回0
    if(i==0)
    {
         //子进程
         do_work();
         exit(0);
    }
    while(1)//轮询等待
    {

        //父进程
        pid_t ret = waitpid(i,NULL,WNOHANG);//等待成功返回所等待进程的id
        if(ret==0)
        {
            cout<<"等待中"<<endl;
        }
        else if(ret==i)
        {
            cout<<"等待成功,所等待进程的id:"<<ret<<endl;
            break;
        }
        else
        {
            cout<<"等待失败"<<endl;
            break;
        }
        sleep(1);
    }

    return 0;
}

 


 多进程的等待

void do_work()
{
    int count=3;
    while(count)
    {
        printf("我是子进程,mypid=%d myppid=%d count=%d\n",getpid(),getppid(),count--);
        sleep(1);
    }
}

int main()
{
    int i=0;
    for(i=0;i<10;i++)
    {
        pid_t id=fork();
        if(id==0)//子进程进入
        {
            do_work();
            exit(1);
        }
    }

    for(i=0;i<10;i++)
    {
        pid_t ret = waitpid(-1,NULL,0);//等待任意一个子进程等价于wait
        if(ret>0)
            printf("进程等待成功,pid:%d\n",ret);
    }

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1194901.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于SSM的智能物业管理网站的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

rabbitMq虚拟主机概念

虚拟主机是RabbitMQ中的一种逻辑隔离机制&#xff0c;用于将消息队列、交换机以及其他相关资源进行隔离。 在RabbitMQ中&#xff0c;交换机&#xff08;Exchange&#xff09;用于接收生产者发送的消息&#xff0c;并根据特定的路由规则将消息分发到相应的队列中。而虚拟主机则…

使用 pubsub-js 进行消息发布订阅

npm 包地址 github 包地址 pubsub-js 是一个轻量级的 JavaScript 基于主题的消息订阅发布库 &#xff0c;压缩后小于1b。它具有使用简单、性能高效、支持多平台等优点&#xff0c;可以很好地满足各种需求。 功能特点&#xff1a; 无依赖同步解耦ES3 兼容。pubsub-js 能够在…

快速修复因相机断电导致视频文件打不开的问题

3-5 本文主要解决因相机突然断电导致拍摄的视频文件打不开的问题。 在日常工作中&#xff0c;有时候需要使用相机拍摄视频&#xff0c;比如现在有不少短视频拍摄的需求&#xff0c;如果因电池突然断电的原因&#xff0c;导致拍出来的视频播放不了&#xff0c;这时候就容易出大…

el-table 多表格弹窗嵌套数据显示异常错乱问题

1、业务背景 使用vueelement开发报表功能时&#xff0c;需要列表上某列的超链接按钮弹窗展示&#xff0c;在弹窗的el-table列表某列中再次使用超链接按钮点开弹窗&#xff0c;以此类推多表格弹窗嵌套&#xff0c;本文以弹窗两次为例 最终效果如下示例页面 2、具体实现和问题…

hub.docker访问不了的问题(一步解决)

暂时我也不清楚&#xff0c;但是下面这个网址可以用(可以先用着)Docker Hub Container Image Library | App Containerization (axlinux.top)https://hub.axlinux.top/

美格智能5G RedCap模组顺利完成中国联通5G物联网OPENLAB开放实验室认证

近日&#xff0c;美格智能5G RedCap模组SRM813Q顺利通过中国联通5G物联网OPENLAB开放实验室端到端的测试验收&#xff0c;并获得OPENLAB实验室的认证证书。这标志着该模组产品各项性能均已符合RedCap商用标准&#xff0c;为5G RedCap规模商用奠定了坚实基础。 中国联通5G物联网…

使用WinDbg分析软件突然崩溃的问题

为了测试windbg有多么牛逼&#xff0c;所以仅仅只是测试一下&#xff0c;属于事后诸葛亮型&#xff0c;也只是为了验证一下&#xff0c;把此方法学会即可。 模拟场景&#xff1a; 软件运行后&#xff0c;点击按钮&#xff0c;直接崩溃掉&#xff0c;什么提示都没有。因此&…

统计学习笔记第 1 部分:Hoeffding 的不等式推导与模拟

照片由Unsplash上的Luca Bravo拍摄 1&#xff1a;背景与动机 霍夫丁不等式是数理统计和机器学习 (ML) 中的一个重要的集中不等式&#xff0c;广泛应用于统计学习理论等理论领域以及强化学习等应用领域。 我注意到&#xff0c;在机器学习社区的一些地方&#xff0c;通常将 Hoeff…

图数据库Neo4j详解

文章目录 第一章 图和Neo4j1.1 图数据库概念1.1.1 图论起源1.1.2 节点-关系及图1.1.3 图数据库1.1.4 图数据库分类1.1.4 图数据库应用场景1.1.5 与关系型数据库对比1.1.6 图数据库优势 1.2 Neo4j介绍1.2.1 Neo4j是什么1.2.2 Neo4j特点1.2.3 Neo4j的优势1.2.4 Neo4j的限制1.2.5 …

网络安全(黑客)-高效自学

首先给大家简单介绍一下网络安全&#xff1a; 1.什么是网络安全&#xff1f; 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、…

eNsp使用技巧

文章目录 显示网格对齐到网络水平对齐和垂直对齐 显示所有接口添加文本进入CLI界面数据抓包方式一方式二 显示网格 对齐到网络 水平对齐和垂直对齐 显示所有接口 添加文本 进入CLI界面 数据抓包 方式一 方式二

No source control providers registered

使用vscode时碰到这个问题 git扩展没启动

Linux前言

目录 Linux的应用场景 Linux的应用现状 Linux的版本 操作系统 什么是Linux操作系统&#xff1f; 为什么要用操作系统&#xff1f; 上篇我们介绍了Linux的历史背景和安装环境。 Linux的应用场景 因为Linux操作系统是开源&#xff0c;所以它流向各个领域。 场景1&…

【有限元方法】Newton-Raphson Method

Newton-Raphson Method Linear vs Nonlinear Analysis: At this point, we can conduct a linear analysis no problem ∫ ∑ i , j 1 3 σ i j ε i j ∗ d v ∫ t n ⋅ u ∗ d s ∫ ρ b ⋅ u ∗ d v ⇒ ∫ e [ B ] T [ C ] [ B ] d x ⏟ k e u e ∫ ∂ e [ N ] T t n …

2022最新版-李宏毅机器学习深度学习课程-P50 BERT的预训练和微调

模型输入无标签文本&#xff08;Text without annotation&#xff09;&#xff0c;通过消耗大量计算资源预训练&#xff08;Pre-train&#xff09;得到一个可以读懂文本的模型&#xff0c;在遇到有监督的任务是微调&#xff08;Fine-tune&#xff09;即可。 最具代表性是BERT&…

Arcgis连接Postgis数据库(Postgre入门十)

效果 步骤 1、矢量数据首先有在postgis数据库中 这个postgis数据库中的一个空间数据&#xff0c;数据库名称是test3&#xff0c;数据表名称是test 2、Arcgis中连接postgis数据库中 3、成功连接 可以将数据拷贝或导入到gdb数据库中

Python---练习:把8名讲师随机分配到3个教室

案例&#xff1a;把8名讲师随机分配到3个教室 列表嵌套&#xff1a;有3个教室[[],[],[]]&#xff0c;8名讲师[A,B,C,D,E,F,G,H]&#xff0c;将8名讲师随机分配到3个教室中。 分析&#xff1a; 思考1&#xff1a;我们第一间教室、第二间教室、第三间教室&#xff0c;怎么表示…

FPGA运算

算数运算中&#xff0c;输入输出的负数全用补码来表示&#xff0c;例如用三位小数位来表示的定点小数a-1.625和b-1.375。那么原码分别为a6b‘101101, b6b101011, 补码分别是a6’b110011&#xff0c;b6‘b110101&#xff1b; 如果想在fpga中实现a*b&#xff0c;则需要将a和b用补…

口水战,余承东从没输过,小鹏最终只能低头和解

小鹏汽车创始人何小鹏近日发言称与余承东握手言和&#xff0c;感谢余总的大度&#xff0c;还表示与余承东探讨了技术路线&#xff0c;双方成为好朋友&#xff0c;可以看出这场口水战最终的赢家还是余承东。 这场口水战先以何小鹏吐槽友商的AEB误触太多&#xff0c;还声言99%是假…