Linux进程概念(六):进程控制

目录

进程创建

fork函数

进程终止

终止时干了什么

进程终止的三种情况

main函数的返回值

打印默认退出码

自定义退出码

总结 

进程终止

exit函数

_exit函数

exit和_exit的区别

进程等待

什么是进程等待

为什么要有进程等待

wait函数

waitpid函数

阻塞等待与非阻塞等待

总结 


进程创建

进程 = 内核的相关管理数据结构(task_struct + mm_struct + 页表) + 代码和数据

fork函数

函数原型:pid_t

包含头文件:<unistd.h>和<sys/type.h>(后者为了适应pid_t类型的变量)

返回值:子进程中返回0,父进程返回子进程的pid,出错返回-1(进程太多等原因造成)

父进程调用fork函数,在操作系统内核执行该函数的函数体,执行时内核会做出以下反应:

  • 分配新的内存块和内核数据给子进程
  • 将父进程的部分数据结构内容拷贝至子进程,子进程共享父进程的代码,写时拷贝父进程的数据(子进程的PID、PPID、优先级与父进程等不同)
  • 添加子进程到系统列表中
  • fork返回,开始调度器调度

注意事项:
1、fork函数是操作系统内核提供的函数
2、fork前父进程独立执行,fork后父子两个执行流分别执行

3、fork之后,谁先执行完全由调度器决定

如何理解进程独立性:fork后父子进程的内核管理数据结构(页表等)互相独立,对代码是共享的(代码只有度权限不会改变),父子不写数据时相当于共享,写数据时发生写时拷贝,一人对数据的修改影响不了另一个人

如何理解fork函数有两个返回值:

如何理解调用fork函数后父进程中fork函数的返回值是子进程的pid,子进程中的fork函数的返回值是0:便于父进程对子进程进行标识,从而进行管理

fork的具体问题可以查看这篇文章:http://t.csdnimg.cn/wMBPV

进程终止

终止时干了什么

进程创建时,操作系统先为进程创建内核的相关数据结构task_struct、mm_struct、页表等,然后再加载进程的代码和数据代码(相当于大学录取后高中的学籍信息已经被大学获取,但缴费等操作是到了大学后才进行的)

那么进程终止时也应该先释放曾经的代码和数据所占据的空间,后释放内核数据结构,并让task_struct变为Z僵尸状态(相当于大学毕业后离开宿舍时将自己的东西都带走了,然后学校仍然保留你的一些关键信息存档保留一段时间)

进程终止的三种情况

main函数的返回值

  • 有返回值是因为父进程想要知道子进程运行的结果 
  • 返回值为0,表示进程运行成功
  • 返回值不为0,表示进程运行失败,不同的数字表示不同的失败原因
  • 可以使用默认的错误码,也可以自定义错误码 

打印默认退出码

C语言的sterror函数:http://t.csdnimg.cn/1HvUR 

自定义退出码

  • 结论:代码运行完后是否正确可以通过进程的退出码决定,退出码可默认可自定
  • 补充:代码执行时,出现异常导致提前退出的根本原因是因为该进程收到了OS发给它的信号
  • 信号:kill - l 查看信号找到确定退出原因

C语言的联合体和枚举:http://t.csdnimg.cn/NWYct 

总结 

1、进程终止一共有三种情况:

  • 代码跑完,结果正确
  • 代码跑完,结果不正确
  • 代码执行时,出现异常导致提前退出

2、衡量一个进程退出情况可以依据退出码和退出信号

3、子进程的pcb中有它执行完后的退出码和退出信号信息,子进程结束后,它们会跟随pcb处于Z僵尸状态等待父进程的读取,源码如下:

进程终止

进程有两种终止方式:main函数的return表示进程终止 和 调用exit或_exit函数直接退出进程

exit函数

函数原型:void exit(int status);

  • status:进程的终止原因,父进程通过wait获取
  • status仅有低8位可以被父进程所用,故_exit(-1)时,返回值是255

包含头文件:<stdlib.h>

功能:遇到exit进程直接终止,退出码即status中存放的值

int test3()
{
  int sum = 0;
  for(int i = 0; i < 50; ++i)
  {
    sum += i;
  }
  
  exit(99);
​
  return sum;
}
​
int main()
{
  int ret =  test3();
​
  exit(ret);
  
  return 0;
}

[yyf@hecs-165234 linux101]$ ./myproc 
[yyf@hecs-165234 linux101]$ echo $?
99

_exit函数

函数原型:void _exit(int status);

包含头文件:<unistd.h>

注意事项:

1、_exit 是系统调用,而 exit 是库函数(C语言库函数)

2、_exit和_Exit函数本质上是同一个函数

NAME
       _exit, _Exit - terminate the calling process
​
SYNOPSIS
       #include <unistd.h>
​
       void _exit(int status);
​
       #include <stdlib.h>
​
       void _Exit(int status);

exit和_exit的区别

不同类型的流,默认情况下使用不同的缓存模式:

  • 行缓存模式:缓冲区中遇到\n 或者达到一定长度时自动刷新
  • 全缓存模式:关闭文件或手动调用 fflush函数前都不会进行刷新操作
  • 无缓存模式:调用stderr时,每个字符都立即被发送给终端并打印出来

结论:exit会在进程退出时冲刷缓冲区,_exit不会,因此红框例子中放在缓冲区中的字符产在调用_exit函数导致进程结束后并不会打印到显示器上,而是进程退出时与其他资源一起销毁

进程等待

什么是进程等待

1、任何进程,在退出时,一般必须要被父进程进行等待(退出信息要交给父进程)

产生问题:如果父进程不管Z状态的子进程,直接退出,则造成内存泄漏(子进程的PCB)

为什么要有进程等待

1、父进程通过等待,解决子进程退出的僵尸问题,回收系统资源(等待目标一定要释放资源)

2、获取子进程的退出信息,知道子进程是因为什么原因退出的(可以获取退出原因就更好)

wait函数

函数原型:pid_t wait(int *status)

  • 输出型数:由操作系统填充,指向子进程退出信息的整型指针,若不关心子进程的死亡原因(退出信息),可以将status设为NULL,只返回结束子进程的pid,若关心则将指定子进程的退出信息反馈给父进程(后面有详解)
  • 返回值:等待成功时为子进程的pid,等待失败时为NULL

包含头文件:<sys/types.h> 和 <sys/wait.h>

注意事项:

1、父进程一旦调用wait,就会被阻塞(挂起):

  1. 如果wait参数不为NULL,就等待指定子进程的返回,不返回父进程就一直阻塞,子进程返回后父进程会拿到子进程的退出信息并清理Z状态子进程的pcb,最后唤醒父进程
  2. 如果wait参数为NULL,只要父进程中有一个子进程结束父进程就会拿到子进程的退出信息并清理Z状态子进程的pcb,最后唤醒父进程

2、父进程的等待的本质就是在等待某种资源就绪,等到后操作系统内核就会将位于等待ZMOBIE的等待队列的父进程唤醒,并将相应信息放入int* status指向到内存空间中

对于阻塞队列的内容可以查看:http://t.csdnimg.cn/8N7Nf

waitpid函数

包含头文件:<sys/types.h> 和 <sys/wait.h>

函数原型:pid_t waitpid(pid_t pid,int *status,int options)

返回值:

  • 如果成功等到了一个子进程结束,则返回该子进程PID
  • 如果指定了WNOHANG选项,且没有任何一个子进程已经终止,则返回0
  • 如果出错(例如,指定了无效的 PID 或者调用过程被信号中断),则返回 -1

参数:

  • pid参数:为-1则表示等待任意一个子进程,不为-1则表示等待一个指定子进程

  • 输出型参数:提前开好一片内存空间,将该空间的地址传递给status,子进程返回时,操作系统会将子进程的退出信息放入该空间中

  • status参数:输出型参数,指向子进程的退出信息(退出码 + 退出信号)status是一个四字节三十二个比特位的整型变量,但是它的高两个字节(前十六个比特位)在这里不会被使用,只使用它的低16位,在低十六位中前八位表示退出码,后七位表示退出信号(后八位的最左的一位现在不解释)

打印退出信息、退出码和退出信号: 

  • 进程未受到信号干扰,顺利执行完时的退出码不为0,退出信号为0 

打印因信号终止时的退出码和退出信号:

  • 因信号导致进程终止时,退出码为0,退出信号不为0

WIFEXITED(status):子进程正常返回,则为真(查看进程是否是正常退出)

WEXITSTATUS(status):若WIFEXITED为真,查看子进程的退出码

阻塞等待与非阻塞等待

阻塞等待:父进程在等待子进程返回时什么都不做(稳定可靠)

非阻塞等待:父进程在等待子进程返回时可以去做一些事情(while循环实现)并且在做事情的间隙频繁访问子进程是否返回

waitpid的options参数的取值:

  • 0:表示当前父进程是阻塞等待
  • WNOHANG:表示当前父进程为非阻塞等待,可以与waitpid函数返回值为0时产生互动

非阻塞轮询 = 非阻塞等待 + 循环

父进程利用回调函数在阻塞轮询的时候执行自己的事情:19、1:00:00处

总结 

1、可以自定义退出码,退出信号是由操作系统提供的不能自定义

2、>>移位不会改变数字的比特位,>>=才会,0XFF表示1111 1111,0X7F表示0111 1111

3、父进程的等待是必须的,但是获取子进程的退出信息不是必须的,status设为NULL也行

  也可以参考这位大佬的文章:http://t.csdnimg.cn/syuOf 

~over~

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【前端开发基础知识快速入门】

前端开发基础知识&快速入门 一、VSCode 使用1.1 安装常用插件1.2 创建项目1.3 创建网页1.4 运行效果二、ES62.1 简介2.2 什么是 ECMAScript2.3 ES6 新特性2.3.1 let 声明变量2.3.2 const 声明常量(只读变量)2.3.3 解构表达式2.3.4 字符串扩展2.3.5 函数优化2.3.6 对象优化…

开发日志(20240422):一次以为是跨域但并不是跨域的问题排查记录

1. 日志 在前后端联调的时候&#xff0c;遇到了报错&#xff0c;如下图所示&#xff08;现在再看感觉非常简单了&#xff09;&#xff0c;发现前一个请求通过了&#xff0c;但是第二个请求报错&#xff0c;然后看到 strict-origin-when-cross-origin 条件反射的认为是跨域配置…

流量网关与服务网关的区别:(面试题,掌握)

流量网关&#xff1a;&#xff08;如Nignx&#xff0c;OpenResty&#xff0c;Kong&#xff09;是指提供全局性的、与后端业务应用无关的策略&#xff0c;例如 HTTPS证书认证、Web防火墙、全局流量监控&#xff0c;黑白名单等。 服务网关&#xff1a;&#xff08;如Spring Clou…

初步认识Java

Java之父 Java 语言源于 1991 年 4 月&#xff0c;Sun 公司 James Gosling博士 领导的绿色计划(Green Project) 开始启动&#xff0c;此计划最初的目标是开发一种能够在各种消费性电子产品(如机顶盒、冰箱、收音机等)上运行的程序架构。这个就是Java的前身&#xff1a; Oak (得…

【Node.js工程师养成计划】之打造自己的脚手架工具

一、创建全局的自定义命令 1、打开一个空文件夹&#xff0c;新建一个bin文件夹&#xff0c;在bin文件夹下新建cli.js文件&#xff0c;js文件可以命名为cli.js&#xff08;您随意&#xff09; 2、在cli.js文件中的开头&#xff08;&#xff01;&#xff01;&#xff09;写下面这…

系统服务(22年国赛)—— 磁盘管理(压缩去重)

前言&#xff1a;原文在我的博客网站中&#xff0c;持续更新数通、系统方面的知识&#xff0c;欢迎来访&#xff01; 系统服务&#xff08;22年国赛&#xff09;—— 磁盘管理(压缩&&去重)https://myweb.myskillstree.cn/90.html 目录 StorageSrv 安装并创建vdo 将…

MIT 6.172 笔记 现代硬件算法案例分析

本文是https://en.algorithmica.org/hpc/和MIT 6.172的课后题解析 课程地址&#xff1a; 文章目录 HW2 Profiling Serial Merge Sort测试DEBUG和非DEBUG区别测试inline和非inline区别Coarsening HW3 向量化为什么用负偏移量测量向量化跨步向量化 HW4 Reducer Hyperobjects比较o…

vue echarts 柱状图 堆叠柱状图

echarts堆叠柱状图&#xff08;效果图在文章末尾&#xff09; 1、默认只显示 月度的 数据&#xff0c;手动点击 legend 季度的 数据才会显示&#xff1b; 2、监听左侧菜单栏的宽度变化&#xff0c;图表宽度自适应展示 <template><div><div id"barChart&q…

【MySQL】A01、性能优化-参数监控分析

1、参数监控 1.1、MySQL command 查看 mysql>SHOW STATUS; &#xff08;服务器状态变量&#xff0c;运行服务器的统计和状态指标&#xff09; mysql> SHOW VARIABLES;&#xff08;服务器系统变量&#xff0c;实际上使用的变量的值&#xff09; mysql> SHOW STATUS …

VTK----VTK数据结构详解1(几何篇)

在讲VTK的数据结构之前&#xff0c;我们先了解可视化数据的两个特征&#xff1a;离散性、有规则或无规则。 离散性。当我们使用计算机去表示我们的数据时&#xff0c;一般都是基于有限数量的点做信息的采样&#xff08;或插值&#xff09;&#xff0c;因此可视化的数据是以一种…

C++笔试强训day8

目录 1.求最小公倍数 2.数组中的最⻓连续⼦序列 3.字母收集 1.求最小公倍数 链接 这就是一道普通的数学题。 最大公倍数 A * B / A 与 B之间的最大公约数。 最大公约数求法&#xff1a;辗转相除法(或者可以用<numeric>头文件中的gcd) #include <iostream> us…

Docker基础学习(5.Docker镜像命令)

⭐ 作者简介&#xff1a;码上言 ⭐ 代表教程&#xff1a;Spring Boot vue-element 开发个人博客项目实战教程 ⭐专栏内容&#xff1a;个人博客系统 ⭐我的文档网站&#xff1a;http://xyhwh-nav.cn/ ⭐微信公众号&#xff1a;码上言 文章目录 Docker run流程镜像是什么&a…

AIGC - SD(中英文本生成图片) + PaddleHub/HuggingFace + stable-diffusion-webui

功能 stable-diffusion(文本生成图片)webui-win搭建&#xff08;开启api界面汉化&#xff09;PaddleHubHuggingFace: SD2&#xff0c;中文-alibaba/EasyNLP stable-diffusion-webui 下载与安装 环境相关下载 python&#xff08;文档推荐&#xff1a;Install Python 3.10.6 …

web-traffic-generator:一款功能强大的HTTP和HTTPs流量混淆工具

关于web-traffic-generator web-traffic-generator是一款功能强大的HTTP和HTTPs流量混淆工具&#xff0c;该工具基于纯Python开发&#xff0c;可以帮助广大研究人员在HTTP或HTTPs网络流量中提添加噪声&#xff0c;以此来实现流量混淆的目的。 本质上来说&#xff0c;web-traff…

北大发现了一种特殊类型的注意力头!

检索头的发现或许将有力地帮助大模型领域在提高长上下文推理能力、减少幻觉和压缩KV缓存方面的研究。 从 Claude100K 到 Gemini10M&#xff0c;我们正处于长上下文语言模型的时代。如何在长上下文中利用任何输入位置的信息&#xff1f;北大联合另外四所高校发现了一种特殊类型…

【Redis 开发】Redis持久化(RDB和AOF)

Redis持久化 RDBAOFRDB和AOF的区别 RDB RDB全称Redis DataBase Backup file &#xff08;Redis数据备份文件&#xff09;&#xff0c;也被称为Redis数据快照&#xff0c;简单来说就是把内存中的所有数据都记录到磁盘中&#xff0c;当Redis实例故障重启后&#xff0c;从磁盘读取…

【后端】Thymeleaf模板引擎学习笔记

文章目录 1. java体系模板引擎介绍2. 使用2.1 初步使用2.2. 引用静态资源模板2.3 引用静态资源模板(配置资源路径和后缀)2.4 整合springboot 视频地址 1. java体系模板引擎介绍 FreeMarkerThymeleafVelocity 2. 使用 2.1 初步使用 引入依赖 <dependency><groupId>…

Qt/C++ 波形绘制双缓冲下改善PaintEvent连续绘制卡顿问题(完整代码解析)

音频波形可视化&#xff1a;该控件用于将音频样本数据可视化为波形&#xff0c;常用于音频处理软件中以展示音频信号的时间域特性。 动态数据绘制&#xff1a;控件能够响应外部数据的变化并重新绘制波形&#xff0c;适用于实时或动态的音频数据流。 自定义绘制逻辑&#xff1…

Git操作与异常处理

文章目录 常用操作1、代码拉取2、代码提交3、暂存区状态4、提交代码5、推送远程仓库 异常处理【1】报错信息&#xff1a;Cannot pull into a repository with state: MERGING【2】报错信息&#xff1a;You have not concluded your merge (MERGE_HEAD exists)【3】报错信息&…

SpringCloud整合Ribbon负载均衡器

目录 一、模块一&#xff1a;提供数据 1.1 首先将第一个实例打包 1.2 使用命令行设置不同权重 1.3 打开图形化界面看看权重是否配置成功。 二、模块二&#xff1a;调用模块一 三、修改默认负载均衡策略 四、自定义规则 ​编辑 五、完整代码 5.1 目录结构 5.2 配置文件 …