当前位置: 首页 > news >正文

进程控制(二):进程等待

文章目录

  • 进程控制(二)
  • 进程等待
    • wait函数
    • waitpid函数
    • wait/waitpid获取子进程状态码的过程
    • 进程等待相关的宏
  • 总结


进程控制(二)

延续对于上文进程结束,我们继续对于进程控制进行学习,本文我们主要是对于进程等待进行学习,进程等待,我们在前文初步接触进程的时候,我们知道,进程等待是指我们在运行该进程的时候,在等待资源,当有了资源分配后,便可以运行该进程,在本文中,我们认识的进程等待是指,子进程退出时,先进入僵尸状态,然后父进程进行等待(wait/waitpid)来获取子进程退出信息,这个过程叫做进程等待。

进程等待

进程等待,是子进程退出信息被父进程接收时,父进程处于等待状态的一种描述。

进程等待是指通过系统调用wait/waitpid,来进行对子进程进行状态检测与回收的功能。

  • 子进程退出时,如果父进程没有接收信息,那么会导致僵尸进程的问题,造成内存泄漏,所以父进程必须通过进程等待来回收子进程退出信息。(必要
  • 通过回收子进程的退出信息,也可以知道子进程退出码,以及是否出现异常,status。(可选

所以,我们必须要实现进程等待,防止内存泄漏,对于得到的子进程退出信息,我们可以选择性的利用,可有可无,看自己需求。

wait函数

wait函数,可以实现进程等待,只有一个参数,status,输出型参数,可以获得子进程退出信息

在这里插入图片描述

wait函数在2号手册上,头文件也可以表明,wait函数以及waitpid函数是系统调用接口,通过该函数来访问操作系统,使得操作系统对于子进程进行回收处理。

在这里插入图片描述

core dump,以后会用到,现在不需要掌握,只需要知道,这是用来进行调试的。

#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>#define N 10void RunChild()
{int cnt=5;while(cnt){printf("Child pid: %d, parent pid: %d\n",getpid(),getppid());//获取pid和ppidsleep(1);cnt--;}//printf("Child pid: %d, parent pid: %d\n",getpid(),getppid());//获取pid和ppid//sleep(15);
}int main()
{//实现创建子进程,并对于子进程进行等待for(int i=0;i<N;i++){pid_t id=fork();//创建子进程if(id==0){RunChild();exit(i);//退出码}//父进程执行下面信息printf("create Child proc : %d success\n",id);}sleep(10);return 0;
}

上述代码,我们并没有是wait,会造成内存泄漏,下面我们来通过父进程来接收子进程的退出信息。

#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>#define N 10void RunChild()
{int cnt=5;while(cnt){printf("Child pid: %d, parent pid: %d\n",getpid(),getppid());//获取pid和ppidsleep(1);cnt--;}//printf("Child pid: %d, parent pid: %d\n",getpid(),getppid());//获取pid和ppid//sleep(15);
}int main()
{//实现创建子进程,并对于子进程进行等待for(int i=0;i<N;i++){pid_t id=fork();//创建子进程if(id==0){RunChild();exit(i);//退出码}//父进程执行下面信息//wait;进程等待printf("create Child proc : %d success\n",id);}//进程等待for(int i=0;i<N;i++){//会实现进程的等待pid_t id=wait(NULL);//wait等待是随机的,等待还没有被接收信息的子进程,有几个子进程就需要等几次。//int status=0;//pid_t id=wait(&status);//传地址,操作系统来进行存储子进程退出信息if(id>0){//printf("wait %d success\n ; exit sig: %d\n",id,WEXITSTATUS(status));printf("wait %d success\n",id);}}return 0;
}

waitpid函数

waitpid函数,其拥有三个参数,功能相较于wait更多,可以认为waitpid可以包含wait的功能,wait的功能比较单一,智能获取状态码status,而且是随机等待子进程。

#include <sys/types.h>
#include <sys/wait.h>pid_t waitpid(pid_t pid, int* status, int options);

参数介绍

返回值pid_t:

  • 大于0,表示等待子进程成功,返回值是子进程的pid
  • 小于0,表示等待子进程失败
  • 等于0,表示等待条件还没有就绪,此时父进程可以做自己的事情

pid参数:

  • 大于0,表示等待指定的子进程
  • pid = -1 ,表示等待随机子进程

status参数:

  • NULL,表示不需要子进程的状态码
  • 反之,作为输出型参数,操作系统将子进程退出信息写入status中

options参数:

  • 0,表示阻塞等待
  • WNOHONG,表示非阻塞等待

在这里插入图片描述

wait/waitpid获取子进程状态码的过程

wait和waitpid都是系统调用,为什么要通过系统调用函数,而不是库函数来实现该功能,这是因为,由于进程具有独立性,相互不影响,所以一般的函数无法访问到另一进程的内容,而系统调用,可以在全局上(操作系统的角度)来找到子进程PCB,得到状态码

等待流程

  1. 子进程运行完毕后,进入僵尸状态(Z),将退出码信息存储到子进程PCB中(exit_code,exit_signal),释放代码,以及数据,保留task_struct结构体信息。
  2. 父进程通过wait/waitpid,通过系统调用,得到子进程PCB中的退出信息,将推出信息,以位图的方式,写入到int类型的status参数,从而父进程得到子进程的推出信息。

exit_code:表示退出码

exit_signal:表示结束信号,也就是判断是否异常,如果为0,表示正常,如果非零,那就是接收了终止信号 kill -num,其中num==exit_signal

实现方式:

exit_signal == status&0x7F == WIFEXITED(status)

exit_code == status>>8&0xFF == WEXITSTATUS(status)

进程等待相关的宏

WEXITSTATUS(status):表示输出退出码(exit_code)

WNOHONG:表示非阻塞等待,用于waitpid的option参数。

WIFEXITED(status):通过状态码,表示子进程是否正常结束(是否异常),如果正常,返回ture

总结

进程等待,是父进程必须要完成的事情,是为了防止内存泄漏,也是为了知道子进程完成任务情况(由状态码得出结论),主要是了解wait/waitpid函数,以及status参数的构成,为什么能表示进程的三种退出情况,以及waitpid函数的非阻塞等待宏WNOHONG,还有退出码WEXITSTATUS,还有判断子进程是否正常退出的宏命令WIFEXITED。

http://www.lryc.cn/news/218224.html

相关文章:

  • SWAT-MODFLOW地表水与地下水耦合模型的建模及应用
  • 使用navicat操纵数据库
  • websocket入门
  • Word里MathType插件符号表消失了
  • 利用MySQL玩转数据分析之基础篇
  • 【ML】分类问题
  • python @classmethod装饰器作用 与 使用 类方法 实例方法
  • layui form 中input输入框长度的统一设置
  • 【WSL/WSL 2-Redis】解决Windows无法安装WSL Ubuntu子系统与Redis安装
  • 数据结构(四)--队列及面试常考的算法
  • PMIC、电源管理MAX77646ANP、MAX77647AANP、MAX77675AEWE、MAX77847AEWL DC-DC 开关稳压器
  • 5W2H分析法:全面思考和解决问题的实用工具
  • 01 向量基本概念
  • QMS质量检验管理|攻克制造企业质量检验难题,助力企业提质增效
  • Visual Components Robotics OLP解决方案 北京衡祖
  • React——简便获取经纬度信息
  • 如何修改设置360浏览器内核模式
  • spring boot 定时任务@Scheduled(cron = ““)不可用时并且注入失败时——笔记
  • R语言用jsonlite库写的一个图片爬虫
  • Linux多线程编程- pthread_self()
  • APM建设踩了哪些坑?去哪儿旅行分布式链路追踪系统实践
  • ASTM F963-23美国玩具安全新标准发布
  • swift语言下SurfGen库做的爬虫是什么样的 ?
  • Vue纯CSS实现掷色子
  • 使用vscode开发uniapp项目常用的辅助插件,提升开发效率
  • python脚本监听域名证书过期时间,并将通知消息到钉钉
  • 那些看起来高大上的封装函数
  • go语言 | grpc原理介绍(三)
  • 记一次heapdump泄漏获取服务器权限
  • 大疆Livox MID-360安装ROS1/2驱动 Ubuntu20.04