【Linux笔记】进程等待与程序替换

一、进程的终止

1、进程退出码

在讲解进程的终止之前,先要普及一下进程的退出码概念。

我们父进程之所以要创建子进程,就是为了让子进程运行不一样的任务,那么对于子进程执行的这个任务执行完毕后的结果是否正确或者是否出差错,我们父进程要对这个结果进行验收。

从而就引出了进程退出码和进程退出信号的概念,其中退出码就是main函数的返回值:

我们在命令行中可以使用“echo $?”这串指令来查看最近一个进程的退出码:

如果我们将main函数的返回值改成其他数,那echo $?查出来的值也会随之变化:

一般默认的退出码为0则表示程序运行正确,是其他数则表示程序出了问题,即运行失败。

所以0表示成功,非0就表示失败,具体非零的数字那个对应的是哪种错误,我们可以自己定义。

当然C语言内置的也有一套错误码对应的字符串解释,我们可以调用strerror这个函数来查看:

2、进程终止的方法

在main函数中直接return

在main函数中直接return的方法其实上面已经演示过了,这个其实很容易理解,main函数是程序的入口也是程序结束的地方,所以我们父进程需要回收的就是main函数的返回情况。

使用exit接口

还还有一种方式就是,使用exit接口,这是一个C语言提供的接口:

如果仅放在main函数中,其实它和return是同级的,但是它其实比return的级别还要高,因为它放在任何地方都可以让程序直接结束:

从其运行的结果我们可以看出exit的级别是要比return高的,因为程序的退出码为5,而且后面的打印语句也没有执行。

使用_exit系统调用

还有一个与exit类似的接口_exit也可以用来结束进程:

它是一个系统调用,它的正常使用其实是和exit接口执行的结果一样的,比如把上一段程序中的exit改成_exit后,我们会发现它们执行的结果一模一样:

exit与_exit的区别

那它两到底有什么区别呢?

它两的区别其实就在于它们前者是C库函数,后者是系统调用。

我们先来看一个现象:

我们会发现,程序执行后确实是成功了,因为退出码正确了,但是程序并没有输出任何结果。

不急我们再来对程序进行微微的改动,在printf里面加上\n:

加上\n之后就打印出来了。

然后我们可以再对比一下exit:

经过观察会发现,exit不论是否加上\n它都有结果打印出来,那这是怎么一回事呢?

其实上面的结果的本质就是exit在退出前会刷新缓冲区,而_exit在退出前不会刷新缓冲区。因为缓冲区的刷新条件之一就是遇到了\n,所以只要加上了\n,exit和_exit都会有结果输出,而从_exit退出之前没有刷新缓冲区的结果来看,我们可以推测出缓冲器肯定不在操作系统内部。

道理就是_exit是系统调用肯定是比库函数exit更接近操作系统内部的,但是偏偏exit刷新了,而_exit没有刷新,如果缓冲区是在操作系统内部,那exit都刷新了,为什么更接近操作系统的_exit没有刷新呢?

二、进程等待、

我们知道,如果子进程先于父进程退出,那么子进程就会变成僵尸进程,如果僵尸进程一直不被回收,就会造成内存泄漏问题。

所以,进程等待就是为了回收子进程从而解决子进程僵尸问题造成的内存泄漏而生的。

1、如何进程进程等待

wait的使用

解决进程等待,我们使用的是wait系统调用:

#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status);
返回值:
成功返回被等待进程 pid ,失败返回 -1
参数:
输出型参数,获取子进程退出状态 , 不关心则可以设置成为 NULL
其中的它的参数我们可以先不管,直接传NULL即可。
运行结果:

解释wait的阻塞等待

而且wait的等待方式为阻塞等待,所谓阻塞等待即父进程在等待子进程的过程中会一直停滞着,不会执行任何任务,下面以一个例子来演试一下:

代码:

运行结果:

从结果我们可以看出,在子进程执行期间,父进程其实也已经在执行了,但是一直到子进程执行完毕之后父进程才执行结束。所以在子进程执行期间,父进程一直在做阻塞等待。

waitpid的使用

waitpid相比于wait来说选择性更多,wait只能等待任意一个进程,而waitpid既能等待任意一个进程也能等待指定进程,wait只能阻塞等待,而waitpid既能阻塞等待也能非阻塞等待。

pid_ t waitpid(pid_t pid, int *status, int options);
返回值:
    当正常返回的时候 waitpid 返回收集到的子进程的进程 ID
    如果设置了选项 WNOHANG, 而调用中 waitpid 发现没有已退出的子进程可收集 , 则返回 0
    如果调用中出错 , 则返回 -1, 这时 errno 会被设置成相应的值以指示错误所在;
参数:
   pid
      Pid=-1, 等待任一个子进程。与 wait 等效。
      Pid>0. 等待其进程 ID pid 相等的子进程。
   status:
      WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常        退出)
      WEXITSTATUS(status): WIFEXITED 非零,提取子进程退出码。(查看进程的退出           码)
  options:
      WNOHANG: pid 指定的子进程没有结束,则 waitpid() 函数返回 0 ,不予以等待。若正常        结束,则返回该子进
      程的 ID
比如在上面的代码中,我们将wait直接改成waitpid,然后将第一个参数改成-1或子进程的id值,结果都是一样的:
其中第三个参数设置为0表示的是阻塞等待,第二个参数先不管。

解释waitpid的第二个参数

上面说过进程等待其实是为了解决子进程僵尸状态所造成的内存泄漏问题,但是进程等待还有第二个目的,就是检查子进程的运行结果,即获取子进程的退出码和终止信号。而这个工作就是有waitpid的第二个参数来做的。

wait和waitpid都有这个status参数,它其实是一个输出型参数,即通过外部传参的方式,在内部对参数进程修改,然后外部得到对应的状态。

这个status虽然是一个32位的整型,但我们并不整体使用它,而是只是用它的低16位:

但是我们想直接通过打印出status的只来判断退出信息的话,是有点奇怪的,例如:

正如上面所说的,status并不是整体使用的,而是在进程正常退出时,退出码“直接被放到次低八位”的:

如果想要提取出10来,有两种方法,一种是直接进行位运算,一种是使用上面提供的接口:WEXITSTATUS。

位运算有点儿不好记,而且久了也容易忘,所以我这里就只演示使用函数的情况:

再来演示一下进程异常退出的情况,进程异常退出时,退出码其实是没有意义的,所以我们主要看的是,终止信号。

比如我们可以设置一个常见的空指针异常:

这里就只能使用位运算了,这里的位运算没什么,记住就行。

如果不想记的话,也可以用上面提到的WIFEXITED函数来直接判断子进程是否正常退出,只是不能看出进程异常对应的信号值:

waitpid等待多个进程

那么如何使用waitpid来等待多个子进程呢?

其实很简单,我们创建多个子进程使用的是循环的方式,那我们在等待的时候也使用循环等待即可,先演示阻塞等待的。

演示waitpid的轮训等待(非阻塞等待)

waitpid的第三个参数options默认支持两种等待方式,阻塞等待和非阻塞等待。设置为0表示阻塞等待,而设置成另一个数(宏)WNOHONG则表示,非阻塞等待。

而如果我们直接像使用wait一样使用waitpid的非阻塞等待的话,就会发现父进程直接就结束了,并没有继续等:

显然父进程是并没有成功回收子进程的。因为它先于子进程退出了。

如果我们想让如进程成功回收子进程,就必须使用循环的方式:

三、程序替换

1、程序替换与创建子进程的区别

我们之前是通过创建子进程的方式来让进程“分流”的执行不同的任务,但是子进程执行的任务本质上还是父进程代码的一部分。如果我们想要让子进程执行新的代码和访问新的数据,不再和父进程有瓜葛,就得使用进程替换的方式。

2、进程程序替换的接口

先介绍execl接口

execl这个接口可以为我们执行进程替换的工作,所谓的进程替换其实并不是创建新进程,而是将进程的代码和数据替换:

它的第一个参数表示你要替换的进程的路径+文件名,而后面的可变参数列表则表示你想要怎样执行这个进程,因为各种进程执行所对应的执行选项不同,所以这里需要用可变参数列表,需要注意的是在可变参数列表的最后,一定要传一个NULL,表示参数传递完毕。

先拿我们最常用的“ls”这个指令来演示:

这样我们就可以在我们自己写的C语言代码中调用我们系统的指令了。

然后我们再来看一个现象:

上面的结果中只打印了replace before而没有打印replace after,这其实就说明了进程替换其实是将代码替换掉的。代码都不同了,当然就没有打印啦。

然后我们再来看看它有没有创建新进程:

从结果可以看出,前面创建的子进程后后面付进程等待到的子进程id是一样的,所以进程替换并没有创建新进程。

execlp:

execlp与execl的区别在于,execl需要传文件路径+文件名,而execlp只需要传文件名就行了,多出来的这个p可以理解为自带路径path的含义:

execv:

这个接口,与之前两个不同之处在于,它后面的命令函参数是一个一个数字的形式传递的。他后面的这个v其实就是vector的意思:

剩下的几个接口其实在介绍完上面的三个接口之后,就可以类推出来他们的含义和用法了,如上所述,如果带‘l’则表示后面的命令函参数一列表的形式传递,如果带‘p’则表示它是自带路径的,传第一个参数的时候就只需要传文件名即可,如果是带'v'的,则表示他后面的命令行参数是以数组的形式传递。

以此类推即可。

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

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

相关文章

将 pyparamvalidate 项目,发布至 pypi

目录 一、前置说明1、总体目录2、相关回顾3、本节目标 二、操作步骤1、项目目录2、编写 pyproject.toml 文件3、编写 LICENSE 文件4、编写 README.md 文件5、升级 pip、build、twine 工具6、打包发布的版本7、测试发布至 TestPyPI8、创建测试项目&#xff0c;测试发布结果9、正…

SSM框架学习笔记04 | SpringMVC

文章目录 一、SpringMVC简介二、 请求与响应1. 请求映射路径2. get请求与post请求3. 响应 二、REST风格1.简介 三、 SSM整合四、拦截器1. 定义拦截器2.配置拦截器3.拦截器执行顺序4.拦截器参数5.多个连接器工作流程分析6.拦截器链的运行顺序 一、SpringMVC简介 SpringMVC技术与…

AI嵌入式K210项目(3)-GPIO控制

文章目录 前言一、背景知识二、背景知识二、开始你的表演代码实现 总结 前言 前面介绍了开发板和环境搭建的基本情况&#xff0c;接下来我们开始学习使用C进行裸板开发&#xff0c;本节课先来学习下K210最基础的功能&#xff0c;引脚映射和点灯。 在开始具体学习之前&#xff…

java数据结构与算法刷题-----LeetCode96. 不同的二叉搜索树

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 很多人觉得动态规划很难&#xff0c;但它就是固定套路而已。其实动态规划只…

TRB 2024论文分享:融合Transformer和自监督学习的长时交通流预测模型

TRB&#xff08;Transportation Research Board&#xff0c;美国交通研究委员会&#xff0c;简称TRB&#xff09;会议是交通研究领域知名度最高学术会议之一&#xff0c;近年来的参会人数已经超过了2万名&#xff0c;是参与人数和国家最多的学术盛会。TRB会议几乎涵盖了交通领域…

Ceph的介绍与部署

目录 存储基础 单机存储设备 DAS&#xff08;直接附加存储&#xff0c;是直接接到计算机的主板总线上去的存储&#xff09; NAS&#xff08;网络附加存储&#xff0c;是通过网络附加到当前主机文件系统之上的存储&#xff09; SAN&#xff08;存储区域网络&#xff09; 单…

基于ssm的数学课程评价系统的设计与开发+jsp论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本数学课程评价系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息…

List转数组,使用toArray时,new String[0] 的数组空间大小怎么传?

我们在日常开发中&#xff0c;经常遇到List转数组&#xff0c;数组转List的场景。当我们List转数组时&#xff0c;一般使用这种方式&#xff1a; String[] queryTaskIdArr queryTaskIds.toArray(new String[0]); 但是toArray方法中的入参有什么需要注意的呢&#xff1f; 如下…

【架构】docker实现集群主从扩容【案例3/4】

实现集群主从扩容 当整个集群扛不住流量的情况时&#xff0c;需要给集群扩容增加设备&#xff0c;由3主3从&#xff0c;扩为4主4从。实现&#xff1a; 示意图如下&#xff1a; 第一步&#xff1a;新创建两个节点&#xff08;redis-node-7&#xff0c;端口6387和 redis-node…

sqli-labs关卡25(基于get提交的过滤and和or的联合注入)

文章目录 前言一、回顾上一关知识点二、靶场第二十五关通关思路1、判断注入点2、爆显位个数3、爆显位位置4、爆数据库名5、爆数据库表名6、爆数据库列名7、爆数据库数据 总结 前言 此文章只用于学习和反思巩固sql注入知识&#xff0c;禁止用于做非法攻击。注意靶场是可以练习的…

数据结构之list类

前言 list是列表类。从list 类开始&#xff0c;我们就要接触独属于 Python 的数据类型了。Python 简单、易用&#xff0c;很大一部分原因就是它对基础数据类型的设计各具特色又相辅相成。 话不多说&#xff0c;让我们开始学习第一个 Python 数据类型一list。 1. list的赋值 输…

【shell】读取表格文件的数据

碎碎念 shell在处理复杂问题的时候不具备优势&#xff0c;如果业务环境能够使用python的话用python又简单又好用&#xff0c;但是很多云平台的现场可能需要shell脚本文件&#xff08;还好是要求bash&#xff09; 但是现在有一个业务场景就是运维人员会把参数写在excel表格中 …

《教育》期刊是什么级别的期刊?是正规期刊吗?能评职称吗?

《教育》以教育行业的各类新闻为重点&#xff0c;积极推广各地教育部门改革经验及优秀成果&#xff0c;努力挖掘教育一线先进单位和个人&#xff0c;充分发挥新闻舆论的监督作用。 收录情况&#xff1a;知网收录 投稿方式&#xff1a;教育类&#xff5c;《教育》省级 出版周期&…

Java 常用加密解密

Java 常用加密解密 常见的加密算法可以分成三类&#xff0c;对称加密算法&#xff0c;非对称加密算法和Hash算法。 对称加密 指加密和解密使用相同密钥的加密算法。对称加密算法的优点在于加解密的高速度和使用长密钥时的难破解性。假设两个用户需要使用对称加密方法加密然后…

B端产品经理学习-B端产品的项目管理

项目管理的作用 指导Roadmap落地 每个节点的项目时间需要按照时间点落地&#xff0c;才不会影响后面的项目事件 为了明确需求&#xff0c;明确研发的工作 避免产研部门因为需求扯皮、研发部门抱怨需求文档不够清晰、在开发过程中增加很多细节需求、增加了研发的工作量、初次…

OPC UA 开源库编译方法及通过OPC UA连接西门S7-1200 PLC通信并进行数据交换[一]

前言 在现代工业自动化领域&#xff0c;OPC UA&#xff08;开放性生产控制和统一架构&#xff09;是一种广泛应用的通信协议。本文将以通俗易懂的方式解释OPC UA的含义和作用&#xff0c;帮助读者更好地理解这一概念。 一、OPC UA的定义 OPC UA全称为“开放性生产控制和统一…

R语言【paleobioDB】——pbdb_orig_ext():绘制随着时间变化而出现的新类群

Package paleobioDB version 0.7.0 paleobioDB 包在2020年已经停止更新&#xff0c;该包依赖PBDB v1 API。 可以选择在Index of /src/contrib/Archive/paleobioDB (r-project.org)下载安装包后&#xff0c;执行本地安装。 Usage pbdb_orig_ext (data, rank, temporal_extent…

简单整理FFmpeg相关命令集

FFmpeg相关命令集 简单整理了FFmpeg相关命令&#xff0c;主要包括ffplay播放控制和媒体播放命令、ffmpeg命令相关参数以及常用的提取音视频等命令。 &#x1f3a1;导航小助手&#x1f3a1; FFmpeg相关命令集1.ffmpeg命令分类查询2.ffplay命令2.1 ffplay播放控制2.2 ffplay命令…

数据绑定,defineProperty,v-on,事件处理

目录​​​​​​​ v-bind单向数据绑定 defineProperty 是v-on的简写 事件处理 v-bind单向数据绑定 从name绑定到v-bind到value单向数据绑定&#xff1a; <input type"text" :value"name"> <input type "text" v-model"na…

领导看了就给我升职加薪的年终总结,我只花5分钟就写完了!

年末正是做总结的时候&#xff0c;如果你正苦于年终总结不知道该如何下手&#xff0c;ProcessOn刚好上线了AI一键帮你生成年终总结的活动&#xff0c;还可以下载成PPT格式&#xff0c;或许可以助你一臂之力&#xff0c;操作起来十分简单。当然&#xff0c;计划也可以一键生成&a…