【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源码中也确实可以看到

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++入门的基础知识

c入门 C是在C的基础之上,容纳进去了面向对象编程思想,并增加了许多有用的库,以及编程范式等。熟悉C语言之后,对C学习有一定的帮助,本章节主要目标: 补充C语言语法的不足,以及C是如何对C语言设计…

手机边听边充音频转接器双盲插系列:便捷充电,畅享音乐6500

在快节奏的生活中,手机已经成为我们不可或缺的日常用品。无论是工作、学习还是娱乐,手机都扮演着重要角色。然而,当我们沉浸在音乐的海洋中时,手机电量不足的困扰却时常打断我们的美好体验。为了解决这一难题,手机边听…

WEB攻防【2】——ASPX/.NET项目/DLL反编译/未授权访问/配置调试报错

ASP:windowsiisaspaccess .net:windowsiisaspxsqlserver IIS上的安全问题也会影响到 WEB漏洞:本身源码上的问题 服务漏洞:1、中间件 2、数据库 3、第三方软件 #知识点: 1、.NET:配置调试-信息泄绵 2、.NET:源码反编译-DLL…

5.23.12 计算机视觉的 Inception 架构

1. 介绍 分类性能的提升往往会转化为各种应用领域中显着的质量提升,深度卷积架构的架构改进可用于提高大多数其他计算机视觉任务的性能,这些任务越来越依赖于高质量的学习视觉特征。在 AlexNet 功能无法与手工设计、制作的解决方案竞争的情况下&#xf…

python 面对对象 类 魔法方法

魔法方法 一、__init__ 构造函数,可以理解为初始化 触发条件:在实例化的时候就会触发 class People():def __init__(self, name):print(init被执行)self.name namedef eat(self):print(f{self.name}要吃饭)a People(张三) a.eat() # in…

K8S认证|CKA题库+答案| 12. 查看Pod日志

12、查看Pod日志 您必须在以下Cluster/Node上完成此考题: Cluster Master node Worker node k8s master …

以太坊钱包

以太坊钱包是你通往以太坊系统的门户。它拥有你的密钥,并且可以代表你创建和广播交易。选择一个以太坊钱包可能很困难,因为有很多不同功能和设计选择。有些更适合初学者,有些更适合专家。即使你现在选择一个你喜欢的,你可能会决定…

深度学习Day-18:ResNet50V2算法实战与解析

🍨 本文为:[🔗365天深度学习训练营] 中的学习记录博客 🍖 原作者:[K同学啊 | 接辅导、项目定制] 要求: 根据本文Tensorflow代码,编写对应的Pytorch代码了解ResNetV2与ResNetV的区别 一、 基础…

小红书云原生 Kafka 技术剖析:分层存储与弹性伸缩

面对 Kafka 规模快速增长带来的成本、效率和稳定性挑战时,小红书大数据存储团队采取云原生架构实践:通过引入冷热数据分层存储、容器化技术以及自研的负载均衡服务「Balance Control」,成功实现了集群存储成本的显著降低、分钟级的集群弹性迁…

开放式耳机2024超值推荐!教你如何选择蓝牙耳机!

开放式耳机的便利性让它在我们的日常生活中变得越来越重要。它让我们摆脱了传统耳机的限制,享受到了更多的自由。不过,市面上的开放式耳机种类繁多,挑选一款既实用又实惠的产品确实需要一些小窍门。作为一位对开放式耳机颇有研究的用户&#…

民国漫画杂志《时代漫画》第18期.PDF

时代漫画18.PDF: https://url03.ctfile.com/f/1779803-1248612707-27e56b?p9586 (访问密码: 9586) 《时代漫画》的杂志在1934年诞生了,截止1937年6月战争来临被迫停刊共发行了39期。 ps:资源来源网络!

内网穿透--Frp-简易型(速成)-上线

免责声明:本文仅做技术交流与学习... 目录 frp项目介绍: 一图通解: ​编辑 1-下载frp 2-服务端(server)开启frp口 3-kali客户端(client)连接frp服务器 4-kali生成马子 5-kali监听 6-马子执行-->成功上线 frp项目介绍: GitHub - fatedier/frp: A fast reverse proxy…

回溯大法总结

前言 本篇博客将分两步来进行,首先谈谈我对回溯法的理解,然后通过若干道题来进行讲解,最后总结 对回溯法的理解 回溯法可以看做蛮力法的升级版,它在解决问题时的每一步都尝试所有可能的选项,最终找出所以可行的方案…

从0开始实现一个博客系统 (SSM 实现)

相关技术 Spring Spring Boot Spring MVC MyBatis Html Css JS pom 文件我就不放出来了, 之前用的 jdk8 做的, MySQL 用的 5.7, 都有点老了, 你们自己看着配版本就好 实现功能 用户注册 - 密码加盐加密 (md5 加密)前后端用户信息存储 - 令牌技术用户登录 - (使用 拦截…

Xilinx(AMD) FPGA通过ICAP原语读取芯片IDCODE实现方法

1 概述 Xilinx每种型号的FPGA芯片都有一个唯一的IDCODE与之对应,同一型号不同封装的IDCODE是相同的。IDCODE的获取方法包括JTAG、ICAP原语、AXI_HWICAP IP核等。获取IDCODE常用于根据芯片型号改变代码的功能,或者对代码进行授权保护,只能在指…

从《红楼梦》的视角看大模型知识库 RAG 服务的 Rerank 调优

背景介绍 在之前的文章 有道 QAnything 源码解读 中介绍了有道 RAG 的一个主要亮点在于对 Rerank 机制的重视。 从目前来看,Rerank 确实逐渐成为 RAG 的一个重要模块,在这篇文章中就希望能讲清楚为什么 RAG 服务需要 Rerank 机制,以及如何选…

现代密码学——消息认证和哈希函数

1.概述 1.加密-->被动攻击(获取消息内容、业务流分析) 消息认证和数字签名-->主动攻击(假冒、重放、篡改、业务拒绝) 2.消息认证作用: 验证消息源的真实性, 消息的完整性(未被篡改…

集合、Collection接口特点和常用方法

1、集合介绍 对于保存多个数据使用的是数组,那么数组有不足的地方。比如, 长度开始时必须指定,而且一旦制定,不能更改。 保存的必须为同一类型的元素。 使用数组进行增加/删除元素的示意代码,也就是比较麻烦。 为…

分布式数据库HBase入门指南

目录 概述 HBase 的主要特点包括: HBase 的典型应用场景包括: 访问接口 1. Java API: 2. REST API: 3. Thrift API: 4. 其他访问接口: HBase 数据模型 概述 该模型具有以下特点: 1. 面向列: 2. 多维: 3. 稀疏: 数据存储: 数据访问: HBase 的数据模型…

你真的会使用Vue3的onMounted钩子函数吗?Vue3中onMounted的用法详解

目录 一、onMounted的前世今生 1.1、onMounted是什么 1.2、onMounted在vue2中的前身 1.2.1、vue2中的onMounted 1.2.2、Vue2与Vue3的onMounted对比 1.3、vue3中onMounted的用法 1.3.1、基础用法 1.3.2、顺序执行异步操作 1.3.3、并行执行多个异步操作 1.3.4、执行一次…