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

进程等待与退出

目录

前言

0.进程如何退出

1.进程status的获取

2.进程status的组成

3.退出status的分用与验证

4.解释一下errno与waitpid输中status参数的关系 

5.status设计 


前言

我们在编写程序的时候,我们往往需要知道这个程序中的某个进程执行情况是怎么样的,在Linux平台下有“退出码”、“退出信号”来描述进程退出的结果,退出的结果会返回给该进程的父进程,对于云服务器来说实际上就是将我们搭载主函数的进程返回bash进程,那么对于我们主函数中创建的一级子进程,进程的结果自然就会返回给我们的主函数。本文要讨论的就是进程如何返回给父进程退出结果,以及推出结果有什么作用。


0.进程如何退出

一个进程有多种退出方式(部分):

①进程运行出错,被强制终止

②对进程发送信号,让进程终止

③使用exit()函数,进程返回结束

④return,函数返回结束

注意:进程一旦退出就一定有对应的退出码(与主函数的return返回值类似) 

1.进程status的获取

int main()
{pid_t id=fork();if(id==0){exit(1);}int status;pid_t rid=waitpid(id,&status,0);std::cout<<"status: "<<status<<std::endl;return 0;
}

在这个示例代码中我们使用fork创建一个子进程并让其使用exit(),让子进程返回,其中返回值为1

pid_t waitpid(pid_t id,int &status,int option)
//等待成功返回等待进程的pid,
传入三个参数,
第一个参数表示要等待进程的id,
第二个参数是一个输出型参数,该参数会获得等待进程的进程退出状态码
第三个参数是关于如何等待的选择,0表示阻塞等待。
图1        程序运行结果

2.进程status的组成

图2        status数据分布

 进程status是一个32位的整数,其中这个整数的高16位不被使用全部被设置为0。对于该整数的低16位,其中的高8位用来存储进程的返回值,就是我们上文说到的使用exit()函数返回的值。其中的低8位,其中的低7位用来储存该进程接收到的信号,低8位的最高位用来存储core dump表示位。

在子进程没有接收到信号的时候,低16位中的高8位被允许使用。当子进程受到来自操作系统的信号的时候,高8位的内容就会失效。

core dump标识位(在博主的信号讲解部分还会在提到):这个标识位表示是否在文件异常或出错的时候,是否生成核心转储文件(core dump file)。这个文件中的内容可以帮助程序员对错误和异常进行分析,但是这个文件中可能包含用户的登入信息,会造成用户信息泄露,所以通常情况这个表示位是关闭的。即此bit位为0(本文默认关闭,即此bit为0)。

3.退出status的分用与验证

在第2部分中我们介绍了进程status的数据组成,本本分来进行验证。 该部分分为两部分进行验证。

先让子进程使用exit()函数进行退出,此时代码可以在不发送信号的情况下正常退出,所以信号接收部分为0,同时我们没有开启core dump标识位,所以整体低八位应该为0。

而后验证,发送信号到进程对进程status码低7位的影响。验证此部分,将子进程中注释的死循环打开,在该死循环中,我们获取子进程的pid,有了子进程的pid我们就可以向该进程发送信号。编译运行程序,我们这里假设向子进程发送9号信号(该信号可以强制终止进程)。

#include <iostream>
#include <unistd.h>
#include <sys/wait.h>int main()
{pid_t id=fork();if(id==0){// while(1)// {//     std::cout<<"i am childpid , my pid is "<<getpid()<<std::endl;// }exit(1);}int status;pid_t rid=waitpid(id,&status,0);std::cout<<"status: "<<status<<std::endl;//打印高八位内容std::cout<<"high_eight_bits: "<<((status>>8)&0xff)<<std::endl;//打印低八位内容std::cout<<"low_eight_bits: "<<(status&0xff)<<std::endl;//打印第八位中的最高位内容std::cout<<"highest_low_eight_bit: "<<((status>>7)&1)<<std::endl;return 0;
}
图3        对进程退出码高八位进行验证
图4        对进程发送信号验证其退出码中的低7位信息

对于图3结果,可做如下解释:

图5        对图3、图4结果解释

注意:这里进程的返回为什么使用exit(),而不使用return,这是因为,return是对函数的值返回,假如子进程调用了其他函数,其他函数可通过return返回一个值,但是子进程不会直接退出执行流。但是使用exit(),即使是exit()在被调用的函数中,也会立即令进程返回。当然exit与return在本部分所展示的代码中的子进程返回表现没有差异。 

4.解释一下errno与waitpid输中status参数的关系 

先说结论:二者没有任何关系

errno是在进程执行库函数和系统调用的时候被设置的,用来表明程序中的错误,本质上是一个与进程同级的全局变量,可以用来进行错误提示、区分错误类型、跨函数传递错误信息。

status是属于进程的一个变量,创建在父进程中,数据来源于子进程,由操作系统进行字段的填充与组合。本质上是一种进程间通信的手段,可以让父进程获取子进程的退出状态。

5.status设计 

子进程的等待值实际上是由程序员和操作系统共同维护的,当在进程中出现一些操作系统可容许的错误时,这个时候进程不会崩溃,也就是我们常说的程序运行时错误,比如缺少某些资源,但是不足以让程序崩溃,这个时候子进程的返回值主要由子进程的返回值来控制,程序员在编写代码时,可自行编写一份错误手册,并按照一定的编码方式将这个值返回,而后又操作系统写入status中。但,当进程发生操作系统不可容忍的操作时,比如除0错误、越权访问等,这个时候操作系统会立即出手并向进程发送信号,对进程进行处理,此时程序员设置的错误信息无效,子进程的返回值由操作系统主导。

按照图2中status的表现形式,我们可以做如下推断:

图6        进程返回与信号与运行结果的关系    

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • notepad++软件介绍(含安装包)
  • DFS算法专题(三)——综合练习之【经典回溯】
  • 一次反射型XSS漏洞发现的过程
  • 把iconfont 图标导出为json
  • Flutter 进阶:绘制加载动画
  • (每日一问)操作系统:常见的 Linux 指令详解
  • 人机交互与现代战争
  • 顺序表之创建,判满,插入,输出
  • 设计模式之状态模式 (C++ 实现)
  • 等级保护学习
  • 掏耳勺买哪种效果好?五大可视掏耳勺测评总汇
  • 前端:HTML、CSS、JS、Vue
  • 网络层ip协议
  • 单例的饿汉式,懒汉式的线程安全问题
  • 智能代码编辑器:Visual Studio Code的深度剖析
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • golang 发送GET和POST示例
  • HTTP请求重发
  • JAVA_NIO系列——Channel和Buffer详解
  • Javascript编码规范
  • Laravel 中的一个后期静态绑定
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • OSS Web直传 (文件图片)
  • Redis 懒删除(lazy free)简史
  • Sass Day-01
  • sessionStorage和localStorage
  • Vue--数据传输
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • 关于springcloud Gateway中的限流
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 解决iview多表头动态更改列元素发生的错误
  • 前端面试总结(at, md)
  • 使用common-codec进行md5加密
  • 学习笔记TF060:图像语音结合,看图说话
  • 原生JS动态加载JS、CSS文件及代码脚本
  • const的用法,特别是用在函数前面与后面的区别
  • Nginx实现动静分离
  • ​猴子吃桃问题:每天都吃了前一天剩下的一半多一个。
  • ​字​节​一​面​
  • ‌JavaScript 数据类型转换
  • #1014 : Trie树
  • #define MODIFY_REG(REG, CLEARMASK, SETMASK)
  • #include到底该写在哪
  • #Js篇:单线程模式同步任务异步任务任务队列事件循环setTimeout() setInterval()
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • (2)空速传感器
  • (42)STM32——LCD显示屏实验笔记
  • (C++哈希表01)
  • (day6) 319. 灯泡开关
  • (MTK)java文件添加简单接口并配置相应的SELinux avc 权限笔记2
  • (vue)页面文件上传获取:action地址
  • (论文阅读11/100)Fast R-CNN
  • (没学懂,待填坑)【动态规划】数位动态规划