【Linux的进程篇章 - 进程终止和进程等待的理解】
Linux学习笔记---008
- Linux之fork函数、进程终止和等待的理解
- 1、fork函数
- 1.1、什么是fork?
- 1.2、fork的功能介绍
- 1.3、fork函数返回值的理解
- 1.4、fork函数的总结
- 2、进程的终止
- 2.1、终止是在做什么?
- 2.2、进程终止的3种情况
- 3、进程的终止
- 3.1、进程终止的三种情况
- 3.2、判断是否成功的顺序
- 3.3、如何终止
- 4、进程等待
- 4.1、直接先看结论
- 4.2、进程等待怎么处理呢?
Linux之fork函数、进程终止和等待的理解
前言:
前篇开始进行了解学习Linux的进程优先级、环境变量、地址空间等知识,这篇学习LInux的fork函数、进程终止和等待的理解等相关内容,深入地了解这个强大的开源操作系统。
/知识点汇总/
1、fork函数
前言:
进程:内核的相关管理数据结构(task_struct + mm_struct(内存分配表) + 页表) + 代码和数据
1.1、什么是fork?
直接man fork指令先在手册页查看以下基本信息:
补充:
man fork提示no manual entry for fork,则说明你当前没有安装man手册.
解决方法就是:
root权限下:yum -y install man-pages
基本概念:
fork() 是 Unix/Linux系统中的一个非常重要的系统调用,用于创建一个新的进程,这个新的进程是当前进程的复制品,称为子进程。这个复制过程包括父进程的代码、数据、堆、栈等内容都会被复制到子进程中。
1.2、fork的功能介绍
头文件:
#include <unistd.h>
原型:
pid_t fork(void)
返回值:
-1 ---- fork创建/调用子进程失败
==0 — 返回0是判断创建子进程成功
!=0 — 返回非负整数,表示返回新创建的子进程的进程ID,即,父进程返回的子进程pid
测试代码:
fork语句之后的程序,父子进程共享代码 —> fork创建一个进程,本质是系统中多一个进程;
而多一个进程,也就是多一个进程控制块(task_struct)
父进程的代码和数据是从磁盘加载来的;子进程的代码数据是哪里来的呢?
子进程会默认继承父进程的代码和数据。
我们为什么要创建一个子进程呢?
通常来说,是想要子进程执行和父进程不一样的代码,常规的程序都是单进程,不可能同时跑不同的代码内容。多进程情况下,则是合理的。
对于普通的单进程程序,只能有一个返回值;
对于多进程,那么为什么同一个程序同一个id,会有两个值,即是0又是!=0?
其次,fork怎么会有两个返回值,即返回两次呢?怎么做到的呢?
(涉及虚拟地址空间和父子写时拷贝知识,见这篇文章)
1.3、fork函数返回值的理解
fork也是一个函数,只不过属于系统调用。
然后平常的普通程序中的return在fork执行语句之后,即当执行完fork后,父子代码数据共享,
子进程代码中自然也有了return语句,所以父子进程各自被调度一次,那么自然就返回两次且值可以不同
引出一个概念:理论上,子进程被创建后是空的,自然其代码和数据就从父进程哪里拷贝获取,
就比如有window的任务管理器,有两个子进程由一个父进程创建,当此时关系结束一个子进程会影响其它进程?
当然不会的,逻辑上是父子等关系,实际上是分裂独立的。
所以进程一定要具备的特点就是:
具备独立性,即一个进程出现问题,绝不能影响其它进程。
进程 = 内核task_struct结构体(唯一的pid) + 代码程序(只读/共享的)和数据(父子数据各自独立,原则上数据需要分开)每一个进程都有一个自己唯一的标识符,叫做进程pid
fork()函数返回值:
1.子进程返回0
2.父进程返回子进程pid
为什么父进程返回的是子进程的pid,而子进程返回的是0?
因为父进程返回子进程的pid是对它更好的进程管理,而子进程返回值是判断创建子进程是否创建成功。
即:为了父进程对子进程进行标识,方便管理。
fork的常规用法:
1.一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请求,生成子进程来处理请求。
2.一个进程要执行一个不同的程序。例如子进程从fork()返回后,调用exec函数
fork()调用失败的原因:
1.系统中已有太多的进程。
2.实际用户的进程数超过了限制。
1.4、fork函数的总结
总结:
1.fork()函数在Linux中用于创建一个新的进程,这个新进程是当前进程的复制品,称为子进程。
2.fork()函数的特点在于它只被调用一次,但却能返回两次:一次在父进程中,一次在子进程中。
关于fork()函数的返回值,具体总结如下:
1.在父进程中,fork()函数返回新创建的子进程的进程ID(PID)。
2.这个PID是一个非负整数,用于唯一标识子进程。
3.在子进程中,fork()函数返回0。这是因为在子进程的上下文中,它自己是新创建的进程,所以没有其他的进程ID可以返回。返回0表示子进程成功创建。
4.如果fork()函数执行过程中发生错误,例如由于系统资源不足而无法创建新的进程,那么它会返回一个负值。这个负值通常表示特定的错误码,可以通过检查这个值来确定具体的错误原因。
5.需要注意的是,fork()函数创建的子进程是父进程的副本,包括父进程的代码、数据、堆、栈等内容都会被复制到子进程中。但是,这两个进程有不同的进程ID,并且它们从fork()函数的返回点开始独立执行。
6.因此,通过检查fork()函数的返回值,可以在父进程和子进程中执行不同的代码路径,从而实现并发执行或创建多进程程序。
2、进程的终止
2.1、终止是在做什么?
释放曾经的代码和数据所占据的空间;理解为释放内核的数据结构 ,否则–>僵尸态
2.2、进程终止的3种情况
测试代码:
echo $?
内建命令,打印的都是bash本身内部的变量数据。通常0:成功 非0:标识失败
其中?属于bash维护的一个变量
表示的是,父进程bash获取到的,最近的一个子进程退出的退出码
目的:
告诉父进程(关心结果),我把任务完成得怎么样
0:标识成功
非0:标识失败
非0的数值。一方面可表示失败,另一方面可表示失败的原因。即都有相应的错误描述。
测试代码:
父进程为什么要得到子进程的退出码呢?
答:要知道子进程的退出情况(成功、失败以及失败的原因),本质退出的情况信息,告诉给用户的。
退出码可以使用默认的,同时也可以自定义。
测试代码:
3、进程的终止
3.1、进程终止的三种情况
a、代码跑完,进程正确;
b、代码跑完,进程不正确。
可以通过进程的退出码决定。反馈原因:系统的 && 自定义退出码
c、代码异常终止,提前退出
操作系统发现了你的进程做了不该做的事情,就会被OS自主杀掉该进程。而且一旦出现异常,退出码就没有意义了。
需要关心的是为什么会出异常呢?
1.进程出异常,本质上是由操作系统(OS)向进程发生了一个信号。
2.我们可以查看进程退出的时候,退出的信号是多少,就可以判断,我的进程为什么异常了。
常见情况有:
a、段错误
b、栈溢出
3.2、判断是否成功的顺序
1.先确认是否是异常。
2.不是异常,就一定是代码跑完了。看退出码是否符合预期就行。
结论:
衡量一个进程退出,我们只需要两个数字(反馈给父进程):退出码和退出信号(2^2)。
task_struct()会包含一些字段信息。用于匹配反馈。
比如:exit_code和exit_signal
0 0
0 !0
!0 0
!0 !0
由退出码+退出信号 --》退出进程退出的原因。
3.3、如何终止
a、main()函数return 表示进程终止(非main函数,return,函数结束)
b、代码调用exit()函数,可在代码的任意位置退出,并冲刷缓冲区。
void exit(int status);
c、_exit()–系统调用,与exit的区别不会冲刷缓冲区。
void _exit(int status);
注意:这里所说的缓冲区,不是内核的缓冲区。
4、进程等待
4.1、直接先看结论
任何子进程,在退出的情况下,一般必须都要有父进程进行等待,进程在退出的时候,如果父进程不管不顾(不等待),直到退出进程,导致状态Z(僵尸状态),造成内存泄漏的问题。
为什么?
1.通过父进程等待,解决子进程退出的僵尸问题,回收系统资源(一定要注意)
2.获取子进程的退出信息,知道子进程是因为什么原因退出的(前提是如果需要的话,不是必须的)
4.2、进程等待怎么处理呢?
答:通过两个函数wait()函数和waitpid函数
阻塞等待测试代码:
查看指令:
while :; do ps ajx | head -1 && ps ajx | grep wait_process | grep -v
grep;sleep 1;done
说明:
头文件:
#include <sys/types.h>
#include <sys/wait.h>
函数原型:
pid_t wait(int* status);
返回值:
pid_t:等待成功时,子进程的pid给返回
参数:
status:等待父进程中,任意一个子进程的退出
功能:
用于解决子进程僵尸进程的。(defunct僵尸态)
如何理解阻塞等待子进程呢?
如果子进程没有退出,父进程就会一直处于进行阻塞等待的状态(死等)
子进程本身就是软件,父进程本身就是等待某种软件的条件就绪。
头文件:
#include <sys/types.h>
#include <sys/wait.h>
函数原型:
pid_t waitpid(pid_t pid,int* status,int options);
返回值:
当正常返回的时候waitpid返回收集到的子进程的进程id;
如果设置了选项,而调用waitpid发现没有已退出的子进程收集,则返回0;
如果调用中出错,则返回error会被设置成相应的值以指示错误所在。
1.正常返回时,返回的收集到的子进程id;
2.如果设置了option选项参数为WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
3.如果调用失败,则返回-1,且errno会被设置为相应的值得以指示错误所在。
参数:
pid=-1:等待任意个子进程的pid,与wait相同;
pid>0:等待其进程id与pid相等的子进程;
参数二说明:
status具有特定的格式。(低16位)
1.输出型参数,表示的是输出信息
高八位 – 退出状态
低八位 – 终止信号
2.参数二:status
WIFEXITED(status):若为正常终止子进程的状态,则返回真 — 作用是查看进程是否正常退出
WEXITSTATUS(status):若WIFEXITED非零,提取子进程退出码 ---- 查看进程的退出码
WNOHANG:若pid指定的子进程没有进程,则waitpid()函数返回0,不予以等待,若正常结束,则返回该子进程的ID。
非阻塞等待测试代码:
如果子进程没有退出,而父进程在进行执行waitpid进行等待,阻塞等待(scanf()…的原理)。
所以阻塞就是进程阻塞。
直到等待某种条件的发生(比如子进程的退出)
那么一些非阻塞等待,属于服务器宕机。
阻塞等待和非阻塞的等待本质区别就是判断是否有返回值,是否达成某成条件。
即:pid_t > 0:等待是成功的,子进程退出了,并且父进程回收成功;
pid_t < 0:等待失败了;
pid_t == 0:检测是成功的,只不过子进程还没有退出,需要你下一次进行重复等待。
相关文章:

【Linux的进程篇章 - 进程终止和进程等待的理解】
Linux学习笔记---008 Linux之fork函数、进程终止和等待的理解1、fork函数1.1、什么是fork?1.2、fork的功能介绍1.3、fork函数返回值的理解1.4、fork函数的总结 2、进程的终止2.1、终止是在做什么?2.2、进程终止的3种情况 3、进程的终止3.1、进程终止的三种情况3.2、…...

《策略模式(极简c++)》
本文章属于专栏- 概述 - 《设计模式(极简c版)》-CSDN博客 本章简要说明适配器模式。本文分为模式说明、本质思想、实践建议、代码示例四个部分。 模式说明 方案:策略模式是一种行为设计模式,它定义了一系列算法,将每…...

Python向文件里写入数据
直接上代码 name "测试" data name.encode("utf-8")# w特点:文件不存在则创建文件并在打开前清空 f open("db.txt", mode"wb")f.write(data)f.close()可以在 db.txt 文件里看到一句话 测试name "Testing" …...

【网站项目】校园订餐小程序
🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板ÿ…...

vue-指令v-for
<!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title>vue-指令v-for</title> </head> …...

Python项目1 外星人入侵_外星人
在本章中,我们将在游戏《外星人入侵》中添加外星人。首先,我们在屏幕上边缘附近添加一个外星人,然后生成一群外星人。我们让这群外星人向两边和下面移 动,并删除被子弹击中的外星人。最后,我们将显示玩家拥有的飞船数量…...

导入项目运行后,报错java: Cannot find JDK ‘XX‘ for module ‘XX‘
解决方案: 1、删除.idea和.iml文件 2、右击此module,点击 Open Module Settings 在 Module SDK 中选择所安装的java版本后,点击右下角 Apply,会再生成.idea文件; 那.iml文件呢?操作步骤: 按两下…...

JS rgb,hex颜色值转换
颜色值转化 rgb颜色值转换为hex颜色值(rgb>hex) hex颜色值转换为rgb颜色值(hex>rgb) 代码: const hex2Rgb (hex) > {return rgb(${parseInt(hex.slice(1, 3), 16)},${parseInt(hex.slice(3, 5), 16)},${p…...

Linux| Awk 中“next”命令奇用
简介 本文[1]介绍了在Linux中使用Awk的next命令来跳过剩余的模式和表达式,读取下一行输入的方法。 next命令 在 Awk 系列教程中,本文要讲解如何使用 next 命令。这个命令能让 Awk 跳过所有你已经设置的其他模式和表达式,直接读取下一行数据。…...

基于Springboot的箱包存储系统(有报告)。Javaee项目,springboot项目。
演示视频: 基于Springboot的箱包存储系统(有报告)。Javaee项目,springboot项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构&…...

JavaScript_语法--变量
1.4 变量 变量:一小块存储数据的内存空间 Java语言是强类型语言,而JavaScript是弱类型的语言 强类型: 在开辟变量存储空间时,定义了空间将来存储的数据的数据类型。只能存储固定类型的数据 弱类型: 在开辟变量存储空间…...

P1843 奶牛晒衣服
题目背景 熊大妈决定给每个牛宝宝都穿上可爱的婴儿装 。但是由于衣服很湿,为牛宝宝晒衣服就成了很不爽的事情。于是,熊大妈请你(奶牛)帮助她完成这个重任。 题目描述 一件衣服在自然条件下用一秒的时间可以晒干 a 点湿度。抠门…...

功能强大:JMeter 常用插件全解析
JMeter 作为一个开源的接口性能测试工具,其本身的小巧和灵活性给了测试人员很大的帮助,但其本身作为一个开源工具,相比于一些商业工具(比如 LoadRunner),在功能的全面性上就稍显不足。这篇博客,…...

vulhub之fastjson篇-1.2.27-rce
一、启动环境 虚拟机:kali靶机:192.168.125.130/172.19.0.1(docker地址:172.19.0.2) 虚拟机:kali攻击机:192.168.125.130/172.19.0.1 本地MAC:172.XX.XX.XX 启动 fastjson 反序列化导致任意命令执行漏洞 环境 1.进入 vulhub 的 Fastjson 1.2.47 路径 cd /../../vulhub/fa…...

基于springboot实现教师工作量管理系统项目【项目源码+论文说明】计算机毕业设计
基于springboot实现教师工作量管理系统演示 摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了教师工作量管理系统的开发全过程。通过分析教师工作量管理系统管理的不足,创建了一个计算机管理教师工作…...

[StartingPoint][Tier1]Crocodile
Task 1 What Nmap scanning switch employs the use of default scripts during a scan? (哪些 Nmap 扫描开关在扫描期间使用默认脚本?) -sC Task 2 What service version is found to be running on port 21? 发现端口 21 上运行的服务版本是什么?…...

【Qt】:常用控件(四:显示类控件)
常用控件 一.Lable二.LCD Number 一.Lable QLabel 可以⽤来显⽰⽂本和图⽚. 代码⽰例:显⽰不同格式的⽂本 代码⽰例:显⽰图⽚ 此时,如果拖动窗⼝⼤⼩,可以看到图⽚并不会随着窗⼝⼤⼩的改变⽽同步变化 为了解决这个问题,可以在Widget中重写resizeEvent函数。当用户把窗口从A拖…...

gradio简单搭建——关键词简单筛选【2024-4-11优化】
gradio简单搭建——关键词简单筛选[2024-4-11 优化] 新的思路:标签自动标注界面搭建优化数据处理与生成过程交互界面展示 新的思路:标签自动标注 针对通过关键词,在文本数据中体现出主体的工作类型这一任务,这里使用展示工具grad…...

docker完美安装分布式任务调度平台XXL-JOB
分布式任务调度平台XXL-JOB 1、官方文档 自己看 https://www.xuxueli.com/xxl-job/#1.1%20%E6%A6%82%E8%BF%B0 2、使用docker部署 本人使用的腾讯云,安装docker暴露一下端口,就很舒服的安装这个服务了。 docker pull xuxueli/xxl-job-admin:2.4.03…...

java使用while循环输出2-100的所有素数
使用while循环输出2-100的所有素数,每行输出5个 分析:素数:只能被1和自己整除的自然数 public static void main(String[] args) {int num 2;int count 0;int count1 0;while (num < 100) {for (int i 1; i < num; i) {if (num % i 0) {count;}}if (count 2) {Sys…...

VSCode中调试C++程序
目录 一、准备工作:安装插件 1、C/C插件 编辑 2、CMake插件 3、CMake tool插件 二、调试过程 1、debug 2、打断点 3、调C/C文件 每次重新调试的时候都忘了具体步骤,直接给自己写个备忘录好了。 一、准备工作:安装插件 1、C/C插件…...

Can Transformer and GNN Help Each Other?
ABSTRACT 尽管 Transformer 在自然语言处理和计算机视觉方面取得了巨大成功,但由于两个重要原因,它很难推广到中大规模图数据:(i) 复杂性高。 (ii) 未能捕获复杂且纠缠的结构信息。在图表示学习中,图神经网络(GNN&…...

在隐私计算应用中和数链具备哪些技术特点?
在加速“可信数字化”进程的背景下,我国区块链产业将在打造新型平台经济,开启共享经济新时代的同时,带动数字经济“脱虚向实”服务实体经济。 和数软件在加速数字化进程的同时,进一步服务实体经济,提高实体经济的活力…...

【智能家居入门4】(FreeRTOS、MQTT服务器、MQTT协议、微信小程序)
前面已经发了智能家居入门的1、2、3了,在实际开发中一般都会使用到实时操作系统,这里就以FreeRTOS为例子,使用标准库。记录由裸机转到实时操作系统所遇到的问题以及总体流程。相较于裸机,系统实时性强了很多,小程序下发…...

爬取豆瓣(线程、Session)优化版本
爬取豆瓣(线程、Session)优化版本 该文章只是为了精进基础,对Session、threading、网站请求解析的理解。 此版本没有爬取详情页。还在学习阶段的读者可以尝试一下。 适用于基础刚开始学习爬虫的! 1.改进点: 将普通的r…...

拷贝控制总结
1.拷贝、值与销毁: 拷贝构造函数:如果一个构造函数的第一个参数是自身类类型的引用,且其他(如果有的话)参数都有默认实参,则此构造函数叫做拷贝构造函数;如果我们没有为类定义一个拷贝构造函数…...

无重复字符串的最长子串
题目描述:给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串的长度。 第一次提交记录 class Solution:def lengthOfLongestSubstring(self, s: str) -> int:if not s:return 0lookup set()left res 0for right in range(len(s)):while s…...

javaScript Object.hasOwn()的用法
Object.hasOwn() 如果指定的对象自身有指定的属性,则静态方法 Object.hasOwn() 返回 true。如果属性是继承的或者不存在,该方法返回 false。 备注: Object.hasOwn() 旨在取代 Object.prototype.hasOwnProperty()。 **语法:**Objec…...

MINI2440 开发板 给他干出来了
环境是ubuntu14.04。不要问我为什么是这个版本,因为之前的ubuntu12.04 环境干不出来,你去试试就知道了!各种资源包下载不下来。 输入启动参数: 进入MINI2440:别说心里一万个开心,启动完成,输入p…...

上海人工智能实验室的书生·浦语大模型学习笔记(第二期第三课——上篇)
书生浦语是上海人工智能实验室和商汤科技联合研发的一款大模型,这次有机会参与试用,特记录每次学习情况。 一、课程笔记 本次学习的是RAG(Retrieval Augmented Generation)技术,它是通过检索与用户输入相关的信息片段…...