【Linux】进程终止与进程等待
目录
进程终止
errno
exit和_exit
进程等待
wait和waitpid
宏:WIFEXITED
非阻塞等待
进程终止
下面要谈的一个话题就是进程终止,就是说一个进程退出了,可能有三种情况
1.进程代码执行完,结果是正确的
2.进程代码执行完,结果是错误的
3.进程代码没有执行完,进程出异常了,中途退出了
其实我们写的main函数执行起来就是一个进程,而我们一般写的return 0,就叫做进程的退出码。一般0表示正确执行,第一种情况;而非0表示执行失败,第二种情况。因为main函数的return 0就已经是代码的最后部分了。
为什么用非0表示执行失败呢?因为成功就是成功了,而失败可能会有很多种原因。进程的退出码是给机器看的,要是给人看,就要把退出码转化成错误描述,这个错误描述可以是系统或语言自带的,也可以自定义,下面我们先用strerror函数看一下系统中的错误描述



我们可以看到有很多错误描述,到133个了
这时我们就能解释我们瞎给比如ls 后面一个选项,bash进程,就是命令行解释器报的错是什么了,比如:

这不就是上面的二号错误吗,另外,下面的指令可以查看最近一次进程的退出码

为什么第二次用显示0呢?因为echo $?也是一个进程,它是成功执行的
我们上面说也可以自定义,那就可以创建几个字符串枚举值,并且枚举值是可以表示整数的,这样就可以自己去定义错误码了,比如:

上面我们说了前两种情况,第三种情况是进程没有执行完,中途出现异常了,只要中间出现异常,其实结果对与否就没有意义了。其实中途出现异常本质上就是进程收到了异常信号,就是kill -l那一系列的信号

比如:
8号信号对应的是
SIGFPE(Floating-Point Exception)信号。这个信号用于指示浮点运算异常,比如除以零或溢出等情况。11号信号对应的是
SIGSEGV(Segmentation Fault)信号。这个信号用于指示进程发生了内存段错误,即试图访问无效的内存地址。
并且有一个细节就是这些错误是从1开始的,这跟我们下面的如何用16比特位表示退出码和收到什么信号是有关系的,并且这些大写的字母都是宏定义。
所以进程执行的情况可以由两个数字表示,一个是收到什么信号(0就表示没有收到信号),一个是退出码。
errno
除了进程退出,就是main函数退出,我们还有普通函数退出,那我们如何知道它的运行情况呢?我们也有个存放错误码的东西,叫errno,就是说,函数如果执行失败的话,那么错误码会放在erron这个整形变量里,这个一般库函数才会有这个错误码,因为库函数内部一般是有这个赋值的,我们一般写的函数没有,比如fopen,可以看一下它的返回值

可以看到errno这个东西,下面写一个代码看一下

其实我当前目录根本就没有这个文件,并且是以只读的方式打开文件,所以它肯定会出错,错误信息就存在errno里面,我们也可以看具体字符信息,运行之后就是这样
![]()
exit和_exit
我们如果想让一个进程退出可以用exit或_exit,前者是库函数,后者是系统调用,我们可以来查一下


这里的参数status就是你想让进程退出时的退出码,我们通过一段代码来展示一下它们的区别

我们写这样一个代码,运行完后发现什么都不打印,而把_exit改成exit后就会打印,这就说明exit会刷新缓冲区,其实exit就是封装了_exit,为什么要这样做呢?
其实我们知道库函数和系统调用是上下层关系,不同的操作系统的系统调用是不同的,比如Windows下_exit就用不了,所以这时我们把系统调用再封装一层成为库函数,不同的操作系统封装不同的系统调用,但是它们的库函数的接口就是一样的了,这就通过库函数屏蔽掉了系统调用的差异,就实现了语言的可移植性和跨平台性,所以不同的操作系统就会安装不同的库文件。并且这里的缓冲区是库级别的缓冲区,所以系统调用是无法刷新的,如果是操作系统级别的,那就会刷新,因为操作系统不会让它白白占着空间的。
进程等待
我们之前说过,父进程要回收子进程的PCB来拿到子进程的退出信息,如果父进程不管不顾,子进程就会进入僵尸状态,就会造成内存泄漏,这时就算kill -9也无能为力,因为谁也不能杀死一个已经死掉的进程。而父进程回收子进程就是通过进程等待
wait和waitpid
我们有两种等待方式,分别是wait和waitpid,我们可以man查一下

这里的status是一个输出型参数,通过给一个整型变量的地址,这个函数内部就可以将退出信息写入到这个地址中,如果不想让它写入可以给NULL;pid就是要等待的子进程的pid,如果是-1的话,那么等待任一子进程,这时与wait等效;options是确定父进程是阻塞等待还是非阻塞等待
我们再看一下返回值是什么意思

就是说:如果成功等待到了子进程结束,就返回子进程的PID;如果等待失败(如果pid参数指定的子进程不存在或不是当前进程的子进程或是如果调用被一个信号中断)就返回-1;如果非阻塞等待(WNOHANG)等待后,子进程状态没变,那么返回0。
知道了各个参数和返回值是什么意思,那我们就可以简单的来使用一下wait和waitpid:


我们上面说过,任何进程最终的执行情况可以有两个数字表明,一个是退出码,一个是退出信号,如果收到退出信号,那么最终的退出码没有意义。waitpid就是通过status这个输出型参数拿到这两个数字的,那么这两个数字是怎么存在一个status中的呢?我们来看一下:
我们只用status中32个比特位中的低16位,也就是0-15位,如果进程没有收到退出信号,那么8-15位就表示子进程的退出码,所以我上面获取退出码时是先进行位右移8位,然后按位与上0xff;如果收到退出信号,那么0-6位表示收到什么退出信号,第七位表示core dump标志,这个标志先不用管,所以我上面是直接按位与上0x7f。
为了验证,我们也可以故意给一个错误的代码,比如访问空指针,这时让程序运行,看看父进程能否分析出子进程的退出信号


我们可以看到,父进程确实等待到了子进程的退出信号11
宏:WIFEXITED
其实不一定非得像上面那样进行位操作才可以得到退出码,我们还可以通过宏来得到退出码或退出信号,像下面这样

wait if exited这个表示如果进程是正常终止,就是没有收到退出信号,那就返回真,所以我们用wait exit status来获取退出码;如果为假,我们用wait terminate signal来获取退出信号。因为只要有退出信号,退出码就没意义,退出码有意义时没有退出信号,所以它们两个只要根据不同情况获取一个即可。
非阻塞等待
我们上面说过waitpid的第三个参数如果是0,那么就是阻塞等待;如果是WNOHANG,就是非阻塞等待,什么是阻塞等待呢?其实就是父进程在等待子进程退出时如果什么都不做,就叫做阻塞等待;如果父进程使用WNOHANG后waitpid后就会立即返回,不管是否有子进程退出,如果等到了子进程退出,返回值就是子进程的pid,如果没有等到就返回0。因为waitpid只会运行一回,有可能等不到子进程,所以一般把它放进一个循环中,并且父进程执行完waitpid后还可以执行自己的工作,我们一般可以这样去实现

进程结束之后只留下进程PCB,所以父进程肯定是通过子进程的PCB获取退出码和退出信号的,我们在Linux源码中也确实可以看到

相关文章:
【Linux】进程终止与进程等待
目录 进程终止 errno exit和_exit 进程等待 wait和waitpid 宏:WIFEXITED 非阻塞等待 进程终止 下面要谈的一个话题就是进程终止,就是说一个进程退出了,可能有三种情况 1.进程代码执行完,结果是正确的 2.进程代码执行完&…...
数据结构_链式二叉树(Chained binary tree)基础
✨✨所属专栏:数据结构✨✨ ✨✨作者主页:嶔某✨✨ 二叉树的遍历 前序、中序以及后序遍历 学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的结点进行相应的操作ÿ…...
python梯度下降法求解三元线性回归系数,并绘制结果
import numpy as np import matplotlib.pyplot as plt # 生成随机数据 np.random.seed(0) X1 2 * np.random.rand(100, 1) X2 3 * np.random.rand(100, 1) X3 4 * np.random.rand(100, 1) y 4 3 * X1 5 * X2 2 * X3 np.random.randn(100, 1) # 合并特征 X_b np.hsta…...
Linux基础(五):常用基本命令
从本节开始,我们正式进入Linux的学习,通过前面的了解,我们知道我们要以命令的形式使用操作系统(使用操作系统提供的各类命令,以获得字符反馈的形式去使用操作系统。),因此,我们是很有…...
原始字面常量(C++11)
原始字面常量(C11) 文章目录 原始字面常量(C11)前言一、原始字面量二、代码示例总结 前言 字面量一般是指数值(12、454等)和字符串(“Hw”、“h\t”),但是有时候我们想表…...
C++|设计模式(〇)|设计模式的六大原则
这里文章只做简要描述,作为扫盲 在软件开发过程中,遵循一定的设计原则可以帮助开发者创建更加灵活、可维护和可扩展的系统。设计模式的六大原则是面向对象设计的核心理念,本文将详细介绍这些原则,并结合实例说明它们的重要性和应用…...
【排序算法】——归并排序(递归与非递归)含动图
制作不易,三连支持一下吧!!! 文章目录 前言一.归并排序递归方法实现二.归并排序非递归方法实现 前言 这篇博客我们将介绍归并排序的原理和实现过程。 一、归并排序递归方法实现 基本思想: 归并排序(MERGE-…...
Mysql自增id、uuid、雪花算法id的比较
MySQL自增id: 优点: 1.简单易用 MySQL自增id 由数据库自动生成。 2.效率高 自增id是按顺序递增的,可以提高插入和查询的效率。 3.索引效率高 自增id可以作为主键或索引列,提高查询效率。 缺点: 1.不适用于分布式系统 在分布式…...
【会议征稿,IEEE出版】第九届信息科学、计算机技术与交通运输国际学术会议(ISCTT 2024,6月28-30)
第九届信息科学、计算机技术与交通运输国际学术会议(ISCTT 2024)将于2024年6月28-30日在中国绵阳举行。 ISCTT 2024将围绕 “信息科学”、"计算机技术”、“交通运输” 等最新研究领域,为来自国内外高等院校、科学研究所、企事业单位的专…...
二十八篇:嵌入式系统实战指南:案例研究与未来挑战
嵌入式系统实战指南:案例研究与未来挑战 1. 引言 1.1 嵌入式系统的重要性及其应用广度 在当今快速发展的技术领域中,嵌入式系统扮演着至关重要的角色。这些系统是专门设计的计算机硬件和软件的组合,旨在执行特定任务,如控制、监…...
探索编程乐趣:绘制螺旋图的奇幻之旅
新书上架~👇全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一、引言:编程的魔法世界 二、绘制螺旋图的准备工作 三、代码实战:…...
C# 语法糖
语法糖 var关键字(隐式类型变量):自动属性:简化的事件访问器:Lambda表达式和匿名方法:扩展方法:LINQ查询:异步编程(async和await):嵌套匿名类型&a…...
ubuntu 安装VMtool 实现复制粘贴
如果只是安装一个根本没有用,而是两个命令都要安装 sudo apt-get install open-vm-tools sudo apt-get install open-vm-tools-desktop引用博客...
智慧仓储新动力:EasyCVR+AI视频智能监管系统方案助力仓储安全高效管理
一、背景 随着物流行业的快速发展和智能化水平的提升,智慧仓储视频智能监管系统已成为现代仓储管理的重要组成部分。本系统通过综合运用物联网、视频分析、边缘计算等技术手段,实现对仓储环境的全面监控、智能分析和高效管理。 TSINGSEE青犀视频汇聚Ea…...
gcc源码分析(AST抽象语法树)
文章目录 三、AST相关1、AST(抽象语法树)1.1 树结点的声明1.2 树结点的结构1.2.1 tree_node联合体1.2.2 tree_base结构体1.2.3 tree_common结构体1.2.4 常量结构体1.2.5 **标识符节点**2、符号绑定,作用域与block树节点2.1 lang_identifier结构体2.2 c_binding结构体2.3 scop…...
ES基础概念
本文不介绍如何使用ES(使用ES见:) 1.ES生态圈 ES: Logstash:数据处理服务程序,解析转换加工数据; Kibana:数据展示、集群管理,数据可视化、ES管理与监控、报表等…...
断更是我的错
打算在暑假每天两个文章,大概是6月20多号开始吧。...
红队攻防渗透技术实战流程:云安全之云原生安全:云堡垒机
红队云攻防实战 1. 云原生安全-防护设备-云堡垒机1. 云原生安全-防护设备-云堡垒机 堡垒机攻防:(意义) https://mp.weixin.qq.com/s/-WcgyVoTCZuPamVtI5MrJw 堡垒机漏洞:(已知)https://avd.aliyun.com/search?q=%E5%A0%A1%E5%9E%92%E6%9C%BA 云堡垒机:(云攻防) http…...
Down with typename
1. 隐式类型名的详情 C20 之前,typename 在一些其他情况下是不必要的: • 指定继承类的基类型时 • 在构造函数中将初始值传递给基类时 • 在类声明中使用类型成员时 #include <iostream> struct Impl {Impl(){ std::cout << "Impl ctor" &…...
CSS3背景与渐变
背景与渐变 background-size background-size 属性用于设置背景图像的尺寸。您可以指定绝对或相对单位,或者使用关键词来控制背景图像在元素背景区域中的大小。 .element {background-size: [length | percentage | cover | contain] | [length | percentage] [length | per…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
