【Linux的进程篇章 - 进程终止和进程等待的理解】

news2025/6/22 21:42:07

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:检测是成功的,只不过子进程还没有退出,需要你下一次进行重复等待。

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

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

相关文章

数据结构-移除元素(简单)

题目描述 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出…

pycharm debug 的时候 waiting for process detach

当你使用pycharm debug或者run的时候&#xff0c;突然出现了点不动&#xff0c;然后一直显示&#xff1a;waiting for process detach 可能是以下问题&#xff1a; 1、需要设置Gevent compatible pycharm一直没显示运行步骤&#xff0c;只是出现waiting for process detach-C…

Day04-SHELL自动化编程-循环与颜色函数库

Day04-SHELL自动化编程-循环与颜色函数库 11. 必知必会核心命令11.1 命令概述11.7 案例11.8 小结 12 Shell编程-循环12.1 循环概述12.2 for循环1&#xff09;最常用的for循环格式2&#xff09;c语言格式for循环3&#xff09;for循环格式及应用场景4&#xff09;案例 12.3 while…

数据结构(三)----栈和队列

目录 一.栈 1.栈的基本概念 2.栈的基本操作 3.顺序栈的实现 •顺序栈的定义 •顺序栈的初始化 •进栈操作 •出栈操作 •读栈顶元素操作 •若使用另一种方式: 4.链栈的实现 •链栈的进栈操作 •链栈的出栈操作 •读栈顶元素 二.队列 1.队列的基本概念 2.队列的基…

【TensorRT】TensorRT C# API 项目更新 (1):支持动态Bath输入模型推理(下篇)

4. 接口应用 关于该项目的调用方式在上一篇文章中已经进行了详细介绍&#xff0c;具体使用可以参考《最新发布&#xff01;TensorRT C# API &#xff1a;基于C#与TensorRT部署深度学习模型》&#xff0c;下面结合Yolov8-cls模型详细介绍一下更新的接口使用方法。 4.1 创建并配…

Ubuntu配置VScode的C++环境

在Ubuntu系统下配置C环境&#xff0c;并运行helloworld 1. 下载VScode 我这里使用的是星火应用商店&#xff0c;在商店里面可以直接下载安装 http://spark-app.store/ 2.创建文件夹 3.启动VScode并打开该文件夹 4.安装以下几个扩展 PS&#xff1a;Clang这个插件别安装&…

Spark 应用程序优化和调优总结

文章目录 前言调整 Spark 默认配置查看和设置 Spark 配置信息动态扩展集群负载 数据的缓存和持久化DataFrame.cache()DataFrame.persist()何时缓存和持久化何时不缓存和持久化 Spark 中的 JOINs广播连接排序合并连接 总结 前言 本文总结了 Spark 中比较重要和常用的调优手段&a…

docker pull镜像的时候指定arm平台

指定arm平台 x86平台下载arm平台的镜像包 以mysql镜像为例 docker pull --platform linux/arm64 mysqldocker images查看镜像信息 要查看Docker镜像的信息&#xff0c;可以使用docker inspect命令。这个命令会返回镜像的详细信息&#xff0c;包括其元数据和配置。 docker i…

【重磅推荐】2024七大零售行业线下开店超全指南大全共452份

如需下载完整PPTX可编辑源文件&#xff0c;请前往星球获取&#xff1a;https://t.zsxq.com/19F4dDDrv 联华快客便利店的加盟手册.docx 好德便利店加盟手册.docx 超市&便利店守则:商品退换货管理.docx 赠品管理制度.doc 选址必看.doc 新人续签考核作业.doc 物流箱管理制度.d…

AugmentedReality之路-平面检测(5)

本文介绍通过AR检测水平平面和垂直平面&#xff0c;并将检测到的平面转化为Mesh 1、在首页添加功能入口 在首页添加一个按钮&#xff0c;命名为Start World Track 2、自定义ExecStartAREvent 创建ARSessionConfig并取名为ARSessionConfig_World 自定义ExecStartAREvent&…

C++ | Leetcode C++题解之第20题有效的括号

题目&#xff1a; 题解&#xff1a; class Solution { public:bool isValid(string s) {int n s.size();if (n % 2 1) {return false;}unordered_map<char, char> pairs {{), (},{], [},{}, {}};stack<char> stk;for (char ch: s) {if (pairs.count(ch)) {if (…

SSH穿透ECS访问内网RDS数据库

处于安全考虑&#xff0c;RDS一般只会允许指定的IP进行访问&#xff0c;而我们开发环境的IP往往是动态的&#xff0c;每次IP变动都需要去修改RDS的白名单&#xff0c;为我们的工作带来很大的不便。 那么如何去解决这个问题&#xff1f; 假如我们有一台ESC服务器&#xff0c;E…

DVWA -File Upload-通关教程-完结

DVWA -File Upload-通关教程-完结 文章目录 DVWA -File Upload-通关教程-完结页面功能LowMediumHighImpossible 页面功能 此页面的功能为选择某个图片文件点击Upload按钮上传&#xff0c;上传成功后得知文件上传路径为DVWA\hackable\uploads。 Low 源码审计 这段 PHP 代码…

双云及多云融合(混合云)

背景&#xff1a;客户对于业务的高可用需求&#xff0c;当发生故障时&#xff0c;业务还能正常使用&#xff0c;如某云机房整体宕机&#xff0c;或云管理服务整体宕掉&#xff0c;导致客户业务不可用&#xff0c;此时&#xff0c;需有业务能顺利切换到灾备云上。 需求&#xf…

【八股】AOP

AOP(Aspect Oriented Programming)&#xff0c;面向切面编程&#xff0c;他是一种编程范式。 作用&#xff1a; 在不改变原始设计的的基础上对其进行功能增强。 几个基本概念&#xff1a; 连接点&#xff1a;所有的方法 切入点&#xff1a;追加功能的方法 通知&#xff1a;追加…

基于小程序实现的社区户口管理的系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;ssm 【…

vue2 二次封装element 组件,继承组件原属性,事件,插槽 示例

测试页面代码 这里主要记录如何封装element的el-input 并且封装后具有el-input原本的属性 事件 插槽 下面为测试页面即组件调用 <script> import CustomInput from /components/CustomInput.vue;export default {name: TestPage,components: { CustomInput },data() …

SpringCloud系列(2)--SpringCloud和SpringBoot技术选型

前言&#xff1a;SpringCloud是微服务架构的一揽子解决方案&#xff0c;SpringBoot是一种技术&#xff0c;要使用SpringCloud&#xff0c;也需要使用到SpringBoot&#xff0c;所以要使用SpringCloud时&#xff0c;必须也要考虑到SpringBoot的适配问题 1、查看SpringCloud和与之…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 4月11日,星期四

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年4月11日 星期四 农历三月初三 1、 中办、国办&#xff1a;加大从优秀社区工作者中招录公务员力度。 2、 即日起&#xff0c;全国铁路实行新的货物列车运行图。 3、 台湾花莲地震死亡人数上升至16人&#xff0c;强震后“地…

在渲染项目instant-ngp使用代码(run.py)实现的补充说明

0 引言 最近&#xff0c;在做一个项目中有需要使用渲染接口&#xff0c;需要使用代码来实现。详细的步骤在文章instant-ngp中run.py的使用_/instant-ngp/./scripts/run.py", line 25, in https://blog.csdn.net/fengbingchun/article/details/129770444?ops_request_misc…