Linux进程控制

Linux进程控制

  • 一.进程创建(fork函数)
  • 二.进程终止
    • 1.退出码的概念
    • 2.查看错误码
    • 3.查看错误码对应的错误信息
      • 1.strerror
      • 2.函数退出时的错误码
      • 2.自定义错误码
    • 4.进程异常
    • 5.exit终止进程
    • 6.总结
  • 三.进程等待
    • 1.为什么要有进程等待
    • 2.wait
    • 3.waitpid
      • 1.函数介绍
      • 2.演示
      • 3.利用位运算分别取出退出码和退出信号编号
    • 4.两个宏
    • 5.非阻塞等待和轮询访问
  • 四.进程程序替换
    • 1.原理
    • 2.小程序
      • 1.execl
      • 2.小程序
    • 3.更改为多进程版本
    • 4.细节性学习各种exec接口
      • 1.execlp
      • 2.execv和execvp
    • 6.补充
      • makefile编译生成多个可执行程序
    • 7.execle
      • 1.execle函数使用
      • 2.execle补充:
    • 8.shell运行原理

一.进程创建(fork函数)

关于fork函数,我们之前已经介绍过了,这里就不再赘述了
(因为我们本文的重点是进程等待和进程程序替换)
详细的大家可以去看Linux进程理解(冯诺依曼体系结构,操作系统,进程概念和基本操作)这篇博客,里面介绍了fork函数
这里再补充几点fork函数的知识点:
在这里插入图片描述

二.进程终止

我们知道,当一个进程退出时,我们肯定是要拿到它的退出信息的
那么我们如何拿到这个进程的退出信息呢?

回想一下:
我们写main函数的时候都会在最后加上return 0;
而对于一个可执行程序而言,执行完main函数之后不就代表这个进程运行完毕了吗?

因此:
我们可以通过main函数的返回值来拿到进程的退出信息

其实main函数的返回值就被叫做进程的退出码

不过一个进程的退出信息不单单只有退出码,还有一个进程退出时的信号编号
下面我们一一来介绍
先来介绍退出码

1.退出码的概念

对于main函数而言
我们平常都会写return 0;
这个0就是退出码

0代表进程正常退出
非0代表进程不正常退出(又称为错误码)
每一个错误码都对应于一种错误信息
下面我们来查看一下错误码

2.查看错误码

bash会记录最近一次进程执行结束时的进程码
echo $?  查看最近一次的进程的退出码
当然退出码也包含错误码

因为我上一个进程正常退出,退出码为0,因此显示0
在这里插入图片描述
下面我们写一个hello world,返回值为2
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
此时运行mycmd,然后发现此时退出码的确为2
那么每一个错误码对应的错误信息是什么呢?

3.查看错误码对应的错误信息

1.strerror

strerror是C语言的库函数
在这里插入图片描述
然后我们把code.c改一下:
在这里插入图片描述
打印一下0~200所对应的错误码来看一下
在这里插入图片描述
这是main函数的错误码
那么普通函数有没有错误码呢?
对于C语言的库函数来说,是有错误码的
但是我们自定义的函数是没有错误码的
不过我们可以自定义错误码来模拟一下

2.函数退出时的错误码

我们要清楚一点:
main函数退出时的返回值:代表该进程退出时的退出码
而其他函数退出时的返回值,仅仅表示该函数调用完毕,返回我们想要得到的值而已

那么我怎么知道某个函数退出时的错误码呢?
比方说fopen这个函数
在这里插入图片描述
我们修改一下code.c
此时我们当前目录下没有test.txt这个文件
下面我用r方式打开这个文件
那么就会打开失败,返回NULL,并且设置errno
在这里插入图片描述
在这里插入图片描述
此时提示我们:
错误码:2 没有这个文件

注意:errno只有C语言的库函数才能用
自定义函数是用不了的,不过我们可以自定义错误码

2.自定义错误码

我们也可以自己设置一些错误码
就像这样:
在这里插入图片描述
假设work函数发生IO错误,返回了1这个错误码
然后我们在调用work函数的这个main函数中接收这个信息
然后打印它的退出信息
在这里插入图片描述
正和我们的意思

4.进程异常

我们介绍完退出码之后,
下面我们来介绍进程退出时的信号编号

我们在平常C语言的学习过程中
都知道如果发生对空指针进行解引用操作时,程序运行时会直接崩溃
其实这个运行时崩溃就是进程异常的一种表现

进程异常:就是进程在运行过程中收到了异常信号

我们可以
使用kill -l来查看进程信号
使用 kill -进程信号编号 进程PID
来给某个特定进程发送进程信号
其实我们之前学的kill -9 进程PID 用来杀死进程就是给进程这个信号让进程退出

在这里插入图片描述
下面我们来演示一下
在这里插入图片描述
mycmd这个进程一直死循环执行
然后我分别

kill -8 PID
kill -11 PID
来让这个进程出现除0异常和段错误

在这里插入图片描述

5.exit终止进程

我们在C语言学习的时候,可能见过这个函数:exit
它是用来终止一个进程的
在这里插入图片描述

其实我们完全可以这样理解:
执行return n等同于执行exit(n),因为调用main的运行时函数会将main的返回值当做exit的参数换言之也可以这么理解:exit(n)就是直接执行main函数的return n;

因此,我们来看这个代码
在这里插入图片描述
在这里插入图片描述
此时这个进程运行到work之后执行到exit(0)时就会终止掉
并不会执行下面的printf

6.总结

在这里插入图片描述

三.进程等待

1.为什么要有进程等待

在这里插入图片描述
那么父进程该如何等待子进程呢?
我们介绍两个函数
1.wait
2.waitpid

2.wait

首先,我们介绍一下wait函数
在这里插入图片描述
下面我们来演示一下使用wait函数回收子进程的过程
在这里插入图片描述
这个代码的意思是:
0~5s内父进程和子进程都在运行
5s时子进程退出,变为僵尸进程
6~10s内子进程一直处于僵尸状态
等到10s时父进程回收子进程后,子进程完全退出,然后父进程又休眠3s后退出
在这里插入图片描述

3.waitpid

1.函数介绍

在这里插入图片描述
最后一个参数options是0的话代表是以阻塞等待的方式等待子进程退出以便回收子进程的退出状态
关于阻塞等待和非阻塞等待我们下面会单独介绍的
下面我们来验证一下

2.演示

在这里插入图片描述
这个代码的意思是:
前5s子进程运行,父进程等待子进程退出,
子进程退出后,父进程立即回收子进程,然后退出

rid>0:等待成功

status:获取退出状态(反馈子进程退出情况的)
第三个参数设置为0:默认采取阻塞等待
在这里插入图片描述

3.利用位运算分别取出退出码和退出信号编号

那么我们能不能分别取出退出码和退出信号编号来呢?
当然是可以的
利用位运算的方法即可:
在这里插入图片描述
总结:

exit_signal(退出信号) == status & 0x7f
exit_code(退出码) == status & 0xff

下面我们来验证一下
在这里插入图片描述
如果正确的话:

exit_signal==0
exit_code==1

在这里插入图片描述
这样好是好,也很巧妙
可是总感觉有些麻烦,还得用位运算才能看到,有没有更直接的方式呢?
当然有啦,就是下面要介绍的两个宏

4.两个宏

WIFEXITED(status): 如果exit_signal==0,那么它的值就是true,否则就是false
WEXITSTATUS(status): 它的值就是exit_code

大家可以这么来记:
1.WIFEXITED:
W:wait等待
IF:if 判断
EXITED:exited:退出信号
判断退出信号是否为02.WEXITSTATUS
W:wait等待
EXIT:exit:退出
STATUS:status:状态
它的值就是退出码

下面我们用一下这两个宏
在这里插入图片描述
在这里插入图片描述
其实他这么设计也是很有道理的
当一个进程运行后,我们最关心的是:它的exit_signal是否为0
因为如果退出信号不是0,就代表进程异常退出,此时退出码是什么对我们来说没有任何意义
因此WIFEXITED这个宏就是用来判断退出信号是否为0的
而WEXITSTATUS这个宏,它的值就是退出码,因为退出码对我们而言还是很有价值的

5.非阻塞等待和轮询访问

在这里插入图片描述
因为大多数情况下,执行非阻塞等待很少能够恰好遇到子进程运行完毕后的状态
因此非阻塞等待一般配合循环一起使用
而且我们知道:

操作系统是要保证运行效率和资源利用率的
因此如果父进程一直去阻塞等待子进程运行完毕的话,那么这段时间内你父进程不就什么都干不了了吗?
这样的话运行效率不就不够好了吗因此非阻塞等待可以让父进程在这段空挡内依然可以运行程序,执行它的任务
提高了运行效率和资源利用率

下面我们来演示一下
在这里插入图片描述
在这里插入图片描述
这个专业术语叫做:基于非阻塞的轮询访问
因为单次查询时不一定马上就能收到子进程运行完毕的回复
因此常常使用循环+单次调用非阻塞等待一起配合使用

这样做有一个优点:在轮询期间可以让父进程做做其他事情
阻塞调用:等待的时候父进程没法做其他事情

四.进程程序替换

1.原理

在这里插入图片描述

2.小程序

首先我们要先明确一点:
Linux中我们平常使用的指令,它本身也是一个程序
因此下面我们实现一个小程序:
用我们的程序执行系统的指令(就是相当于把Linux的系统指令封装一下)

1.execl

在这里插入图片描述
在这里插入图片描述
关于可变参数列表,我们可以以printf来理解一下
这是printf这个函数的原型int printf(const char* format,…)
也正是因此printf可以打印相当相当多的数据
无论你设置多少个格式占位符%d %s %p %f等等等等…

2.小程序

下面我们就来实现一下
在这里插入图片描述
在这里插入图片描述
成功调用了ls命令
可是有几点细节需要说明
在这里插入图片描述
也就是说只有当程序替换执行失败之后,才会执行exec*后续的代码
但是此时因为程序替换执行失败了.所以此时退出状态需要设置为异常的
因此我们可以这样来写,顺便演示一下程序替换失败后的情形
在这里插入图片描述
在这里插入图片描述

3.更改为多进程版本

下面我们创建一个子进程,让子进程去替换为ls这个指令
在这里插入图片描述
在这里插入图片描述
我们发现:
子进程替换成功,不过为什么父进程还能正常运行呢?
因为:进程之间具有独立性,在替换的时候会发生写时拷贝
(注意:我们今天通过这个现象知道了一点:不仅仅数据可以发生写时拷贝,代码也可以!!)

4.细节性学习各种exec接口

小程序已经实现完毕
下面我们就来细节性的学习一下其他的那些接口

1.execlp

在这里插入图片描述
因此我们只需要小小地修改一下我们的代码
在这里插入图片描述
在这里插入图片描述
正常运行

2.execv和execvp

在这里插入图片描述
因此我们可以修改一下我们的代码
依然要注意:最后以NULL结尾
在这里插入图片描述
在这里插入图片描述
正常运行

其实main函数中的命令行参数就是从这里传过来的
shell通过进程替换创建子进程时,将命令行参数传给子进程的main函数时,使用的就是这种方式

在这里插入图片描述
下面我们只需要小小的修改即可
在这里插入图片描述
在这里插入图片描述
我们已经介绍完4个接口了,还差3个接口
其实我们介绍完那3个接口中的1个接口,剩下的两个接口其实大家也就会了
在介绍最后剩下的那一个接口之前,我们先补充一个知识点
能够让我们更好地理解剩下的一个接口和环境变量

6.补充

在这里插入图片描述
因此,我们来写一份C++的代码
在这里插入图片描述
这里补充一点:
因为

makefile从上往下扫描时默认只会形成一个可执行程序

所以为了让makefile能够生成多个可执行程序,我们可以这样做

makefile编译生成多个可执行程序

在这里插入图片描述
.PHONY设置伪目标all
all总是被创建
all依赖于mycmd,cppcmd
没有依赖方法,但是想要生成all,就必需要生成mycmd和cppcmd
然后就可以分别去生成mycmd和cppcmd了
在这里插入图片描述
下面我们在mycmd当中调用cppcmd
在这里插入图片描述
在这里插入图片描述
成功调用

7.execle

1.execle函数使用

在这里插入图片描述
下面我们来演示一下
在这里插入图片描述
将旧程序(C语言程序)中的环境变量交给新程序(C++程序)
在这里插入图片描述
在这里插入图片描述

2.execle补充:

在这里插入图片描述
下面先给大家演示一下
在mycmd当中新增环境变量,在程序替换的时候让cppcmd这个新程序也能拿到该环境变量
在这里插入图片描述
在这里插入图片描述
下面我们来演示一下
借助execle这个函数交给子进程全新的环境变量
在这里插入图片描述
在这里插入图片描述
子进程的确是全新的环境变量

8.shell运行原理

在这里插入图片描述

以上就是Linux进程控制的全部内容,希望能对大家有所帮助!

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

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

相关文章

网工内推 | IT经理,50k*14薪,NP以上即可,七险一金

01 海天瑞声 招聘岗位:IT经理 职责描述: 1、IT基础架构的方案制定、实施和日常维护,包括机房建设运维、服务器配置及运维、网络规划及运维、上网行为管理、电话、电话、监控、门禁等各类弱电系统搭建及运维 2、负责公司环境及网络安全防御体…

【论文阅读】深度学习方法在数字岩石技术中的应用进展

【论文名称】Advances in the application of deep learning methods to digital rock technology 深度学习方法在数字岩石技术中的应用进展 【论文来源】EI检索 【作者单位】长江大学地球物理与油气资源学院、加拿大阿尔伯塔大学土木与环境工程系、东北石油大学地球科学学院、…

微信小程序:用map()将对象数组中的某一项组合成新数组

使用分析 使用map()方法来遍历 info 数组中的每个元素,并整合每一个对象中的某一项进行新数组的重组 效果展示 这里是查询对象数组中的全部name值 原始数据 提取出name的数组 核心代码 var infos items.map(item > item.name); 完整代码(用微信小程…

Facebook广告投放常见错误

在进行Facebook广告投放时,很容易犯一些常见的错误。这些错误可能导致广告投资的浪费,影响广告效果并降低回报。本文小编讲一些常见的Facebook广告投放错误,以及如何避免它们。 1、不明确目标受众 广告的成功与否很大程度上取决于你选择的目…

JVM GUI可视化监控及诊断工具

工具既述 使用命令行工具或组合能帮您获取目标Java应用性能相关的基础信息,但它们存在下列局限: 无法获取方法级别的分析数据,如方法间的调用关系、各方法的调用次数和调用时间等(这对定位应用性能瓶颈至关重要)。要…

人工智能(pytorch)搭建模型22-基于pytorch搭建SimpleBaseline(人体关键点检测)模型,并详细介绍该网络模型与代码实现

大家好,我是微学AI,今天给大家介绍一下人工智能(pytorch)搭建模型22-基于pytorch搭建SimpleBaseline(人体关键点检测)模型,并详细介绍该网络模型与代码实现。本文将介绍关于SimpleBaseline模型的原理,以及利用pytorch框架搭建模型…

蓝桥杯物联网竞赛_STM32L071_9_按键矩阵扩展模块

原理图: 矩阵按键原理图: 实验板接口原理图: 得到对应图: 扫描按键原理: 按键的COLUMN1、2、3分别制0,每次只允许其中一个为0其他都是1(POW1和POW2正常状况为上拉),当有…

快速排序的非递归实现

上期我们实现了快速排序的递归实现,但是我们知道如果递归深度太深,栈就会溢出,所以我们本期将为大家讲述快速排序的非递归实现,我们需要用到栈的数据结构,我们知道栈中的数据全是在堆区开辟的空间,堆的空间…

【docker】Hello World

搜索hello-world镜像 docker search hello-world拉去镜像 docker pull hello-world查看本地镜像 docker images 运行镜像 docker run hello-world查看所有的容器 docker ps -a查询start状态容器 docker ps 输出介绍 CONTAINER ID: 容器 ID。IMAGE: 使用的镜像。COMMAN…

elementui select中添加新增标签

<el-select v-model"ruleForm.eventType" :placeholder"请选择事件类型&#xff0c;可手动添加" ref"template" clearable visible-change"(v) > visibleChange(v, template)"><el-option v-for"item in eventTypeOp…

【离散数学】——期末刷题题库(欧拉图和哈密顿图)

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

遥感图像之多模态检索AMFMN(支持关键词、句子对图像的检索)论文阅读、环境搭建、模型测试、模型训练

一、论文阅读 1、摘要背景 遥感跨模态文本图像检索以其灵活的输入和高效的查询等优点受到了广泛的关注。然而&#xff0c;传统的方法忽略了遥感图像多尺度和目标冗余的特点&#xff0c;导致检索精度下降。为了解决遥感多模态检索任务中的多尺度稀缺性和目标冗余问题&#xff…

从零构建属于自己的GPT系列6:模型部署2(文本生成函数解读、模型本地化部署、文本生成文本网页展示、代码逐行解读)

&#x1f6a9;&#x1f6a9;&#x1f6a9;Hugging Face 实战系列 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在PyCharm中进行 本篇文章配套的代码资源已经上传 从零构建属于自己的GPT系列1&#xff1a;数据预处理 从零构建属于自己的GPT系列2&#xff1a;模型训…

电子取证中Chrome各版本解密Cookies、LoginData账号密码、历史记录

文章目录 1.前置知识点2.对于80.X以前版本的解密拿masterkey的几种方法方法一 直接在目标机器运行Mimikatz提取方法二 转储lsass.exe 进程从内存提取masterkey方法三 导出SAM注册表 提取user hash 解密masterkey文件&#xff08;有点麻烦不太推荐&#xff09;方法四 已知用户密…

剧本杀小程序成为创业者新选择,剧本杀小程序开发

剧本杀作为现下年轻人最喜欢的新兴行业&#xff0c;发展前景非常乐观&#xff0c;即使剧本杀目前处于创新发展阶段&#xff0c;但剧本杀行业依然在快速发展中。 根据业内数据&#xff0c;预计2025年剧本杀市场规模能达到四百多亿元。市场规模的扩大自然也吸引来了不少的创业者…

蓝桥杯航班时间

蓝桥杯其他真题点这里&#x1f448; //飞行时间 - 时差 已过去的时间1 //飞行时间 时差 已过去的时间2 //两个式子相加会发现 飞行时间 两段时间差的和 >> 1import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;public cl…

如何学习Kubernetes,学习K8S入门教程

学习 Kubernetes&#xff08;K8s&#xff09;确实不容易 你的硬件资源有限时&#xff0c;不过别担心&#xff0c;我帮你理清思路&#xff0c;让你在学习 K8s 的路上更加从容。 1、资源限制下的学习方法 当硬件资源有限时&#xff0c;一个好的选择是使用云服务提供的免费层或者…

最新鸿蒙HarmonyOS4.0开发登陆的界面2

登陆功能 代码如下&#xff1a; import router from ohos.router; Entry Component struct Index {State message: string XXAPP登陆State userName: string ;State password: string ;build() {Row() {Column({space:50}) {Image($r(app.media.icon)).width(200).interpol…

【EI会议征稿】第三届电力系统与电力工程国际学术会议(PSPE 2024)

第三届电力系统与电力工程国际学术会议&#xff08;PSPE 2024&#xff09; 2024 3rd International Conference on Power System and Power Engineering(PSPE 2024) 第三届电力系统与电力工程国际学术会议&#xff08;PSPE 2024&#xff09;于2024年3月29-31日在中国三亚隆重召…

DM8/达梦 数据库管理员使用手册详解

1.1DM客户端存放位置 Windows&#xff1a;DM数据库安装目录中tool文件夹和bin文件夹中。 Linux&#xff1a;DM数据库安装目录中tool目录和bin目录中。 1.2DM数据库配置助手 1.2.1Windows创建数据库 打开数据库配置助手dbca 点击创建数据库实例 选择一般用途 浏览选择数据库…