【Linux系统】进程控制

再次理解进程

进程:内核的相关管理数据结构(task_struct(进程控制块PCB),mm_struct(地址空间),页表) + 代码和数据

那么如何理解进程具有独立性

我们之前已经学习过进程控制块啊,地址空间啊,页表啊,他们不都是随着进程的创建而被创建,所以每个进程都有独立的一份这三个结构,那代码是共享的,数据是经过写时拷贝实现进程之间的独立的。

fork函数的返回

fork子进程返回0

fork父进程返回是子进程的pid

为什么父进程返回的是子进程的PID,给子进程返回的是0!!!

首先我们为了父进程方便对子进程进行标识,进而进行管理。

退出码?退出信号?

我们在写c/c++main函数的时候我们是不是往往都会写一个return 0来结束程序的运行!

为什么?

我们在命令行中使用echo $?内键命令

会发现打印出我们刚刚通过./运行的程序的main函数的返回值,我们把return后面设置为什么就会为我们返回什么!

我们知道,内键命令打印的都是bash内部的变量数据。

所以父进程bash获取到的是,最近一个子进程退出的退出码

告诉关心方(父进程),我任务完成的怎么样了!

实际上0代表成功,非0代表失败。

这是程序的退出码

1、2、3……不同的非零值,一方面表示失败,一方面表示失败的原因,

它们都有对应的错误描述,可以以字符串的形式打印出来!

父进程bash为什么要得到子进程的退出码呢?

这是要知道子进程的退出情况(成功,失败,失败的原因是什么?)

这些不都是为了让我们用户看到吗,为我们用户负责!!!

退出码不仅可以使用默认的,也可以进行自定义!

进程的终止

1.进程的终止在做什么?

释放曾经的代码和数据所占用的空间

释放内核数据结构(task_struct)-->我们知道子进程结束,父进程一直在跑但什么事情都不做,子进程进入Z(僵尸态),此时就是task_struct仍然存在的原因,这样就会造成内存泄露的问题。

那么进程的终止不就是回收资源,防止内存泄露吗!

2.进程终止的三种情况?

a.代码跑完,结果正确

可以通过进程的退出码决定!!!

b.代码跑完,结果不正确

同样可以通过进程的退出码决定!!!

c.代码执行时,出现了异常,提前退出了

两个原因,一个系统检测到错误,异常退出,一个我们人为自定义!0退出码

异常退出?(本质是因为进程收到了OS发给进程的信号!)

vs编程运行的时候,崩溃了 --- 操作系统发现你的进程做了不该做的事情,OS杀了进程,一旦出现异常,退出码没有意义了!!!

我为什么出现了异常?原因是?进程出异常,本质是因为进程收到了OS发给进程的信号!

我们可以写一段野指针的操作代码来观察现象

我们发现运行时是出现了段错误,OS提前终止进程。

当我们启动一个进程也可以用kill -11 pid来终止一个进程,其实这就是我们手动发给进程一个信号,让进程异常终止,报的也就是上面的段错误,所以进程出异常,本质是因为进程收到了OS发给进程的信号!

我们可以看进程退出的时候,退出信号是多少,就可以判断我的进程为什么异常了!!!

总结

所以我们面对程序出现错误,两步判断就可

  1. 先确认是否是异常
  2. 不是异常就一定是代码跑完了,看退出码就行。

最后,我们说衡量一个进程退出,我们只需要两个数字退出码,退出信号

这些都是要让父进程bash知道。

其实退出码,退出信号就是在我们的task_struct源代码中的两个个变量

inr exit_code,int exit_signal

3.如何终止?

a.main函数return表示进程终止(非main函数return,函数结束)

b.代码调用exit函数(注意:我们代码的任意位置调用exit,都表示进程退出)

c._exit() --- system call 系统调用接口

exit与_exit都可以让进程退出,那么它俩有什么区别呢?

exit vs _exit:exit会在进程退出的时候,充刷缓冲区,_exit不会,其实这是因为exit是c语言的库函数,它的底层还会调用_exit这个系统调用接口,来操作操作系统,所以充刷缓冲区应该在exit函数用户层的操作。

注意:目前我们说的缓冲区不是内核缓冲区!!!

4.进程等待?

是什么?

结论:任何子进程,在退出的情况下,一般必须要被父进程进行等待。进程在退出的时候,如果父进程不管不顾,退出进程,状态Z(僵尸态),造成内存泄漏。

为什么?

1.父进程通过等待,解决子进程退出的僵尸问题,,回收系统资源(一定要考虑的)

2.获取子进程的退出信息,知道子进程是因为什么原因退出的(可选的功能)

怎么办?

父进程可以通过调用wait/waitpid函数来做到上面两个事情

pid_t wait(int* status)

如果子进程没有退出,父进程其实一直在进行阻塞等待

参数部分,等待父进程中,等任意一个子进程退出。

返回值,等待成功时,子进程的pid。

进程阻塞等待?

子进程本身就是软件,父进程本质是在等待某种软件条件就绪,你如何理解阻塞等待子进程呢?

status是什么呢?

这里就要讲讲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时,wait/waitpid会立即返回,并且释放资源,获得子进程退出信息。
  • 如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞。
  • 如果不存在该子进程,则立即出错返回。
  • wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充。
  • 如果传递NULL,表示不关心子进程的退出状态信息。
  • 否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程。
  • status不能简单的当作整形来看待,可以当作位图来看待。

所以status其实是个输出型参数,我们学过scanf函数,我们从键盘输入数据输出到一个变量中,status就类似把进程退出码与进程退出信号输出到status中,以便父进程拿到子进程的退出信息。

那status是如何存储进程退出码与进程退出信号两个数据呢?

其实status是使用了32位比特位来存储,用status的后7位来存储终止信号,第8位存储core dump(后面讲),再往后8位存储的是进程退出信息,再往后尚未使用。

 测试代码:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>void ChildRun()
{int *p = NULL;int cnt = 5;while(1){printf("I am child process, pid: %d, ppid:%d, cnt: %d\n", getpid(), getppid(), cnt);sleep(1);cnt--;*p = 100;}
}int main()
{printf("I am father, pid: %d, ppid:%d\n", getpid(), getppid());pid_t id = fork();if(id == 0){// childChildRun();printf("child quit ...\n");exit(123);}sleep(7);// father//pid_t rid = wait(NULL);int status = 0;pid_t rid = waitpid(id, &status, 0);if(rid > 0){printf("wait success, rid: %d\n", rid);}else{printf("wait failed !\n");}sleep(3);printf("father quit, status: %d, child quit code : %d, child quit signal: %d\n", status, (status>>8)&0xFF, status & 0x7F);
}

运行结果

这个就是因为段错误,出现异常,进程异常退出!

进程的非阻塞式等待方式代码

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{pid_t pid;pid = fork();if (pid < 0) {printf("%s fork error\n", __FUNCTION__);return 1;}else if (pid == 0) { //childprintf("child is run, pid is : %d\n", getpid());sleep(5);exit(1);}else {int status = 0;pid_t ret = 0;do{ret = waitpid(-1, &status, WNOHANG);//非阻塞式等待if (ret == 0) {printf("child is running\n");}sleep(1);} while (ret == 0);if (WIFEXITED(status) && ret == pid) {printf("wait child 5s success, child return code is :%d.\n", WEXITSTATUS(status));}else {printf("wait child failed, return.\n");return 1;}}return 0;
}

执行结果! 

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

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

相关文章

爆爽,英语小白怒刷 50 课!像玩游戏一样学习英语~

重点!!!(先看这) 清楚自己学英语的目的, 先搞清楚目标&#xff0c;再行动自身现在最需要的东西&#xff1a;词汇量&#xff1f;口语&#xff1f;还是阅读能力&#xff1f;找对应的书籍,学习资料往兴趣靠拢&#xff1a;网上有大量的推荐美剧学习、小说学习&#xff0c;不要被他…

数据库调优-连接池优化

先贴下连接池的相关配置&#xff1a; 连接池参数配置&#xff1a; 字段含义Max Number of Connections最大连接数&#xff1b;做性能测试时&#xff0c;可以填 0 。在开发的项目中按实际代码填写&#xff0c;默认是 20 。Max Wait(ms)在连接池中取回连接最大等待时间&#xf…

Optional学习记录

Optional出现的意义 在Java中&#xff0c;我们经常遇到的一种异常情况&#xff1a;空指针异常&#xff0c;在原本的编程中&#xff0c;为了避免这种异常&#xff0c;我们通常会向对象进行判断&#xff0c;然而&#xff0c;过多的判断语句会让我们的代码显得臃肿不堪。 所以在J…

ETL工具kettle(PDI)入门教程,Transform,Mysql->Mysql,Csv->Excel

什么是kettle&#xff0c;kettle的下载&#xff0c;安装和配置&#xff1a;ETL免费工具kettle(PDI)&#xff0c;安装和配置-CSDN博客 mysql安装配置&#xff1a;Linux Centos8 Mysql8.3.0安装_linux安装mysql8.3-CSDN博客 1 mysql -> mysql 1.1 mysql CREATE TABLE user_…

《黑暗之魂》系列迎来打折:魂三标准版半价134,豪华版199

《黑暗之魂》系列游戏降价促销&#xff0c;现在是购买的好时机&#xff01;想必喜欢挑战和探索的玩家们对这个消息会特别感兴趣。让我们来看看具体的折扣信息吧&#xff01; 首先是《黑暗之魂&#xff1a;重制版》&#xff0c;原价198元&#xff0c;现价仅为99元&#xff01;这…

DSP开发实战教程-国产DSP替代进口TI DSP的使用技巧

1.替换CCS安装路径下的Flash.out文件 找到各自CCS的安装路径&#xff1a; D:\ti\ccs1230\ccs\ccs_base\c2000\flashAlgorithms 复制进芯电子国产DSP官网提供的配置文件 下载链接&#xff1a;https://mp.csdn.net/mp_download/manage/download/UpDetailed 2.替换原有文件 3.…

密码学《图解密码技术》 记录学习 第十三章

目录 第十三章 13.1 本章学习的内容 13.2 PGP 简介 13.2.1 什么是 PGP 13.2.2 关于 OpenPGP 13.2.3关于GNU Privacy Guard 13.2.4 PGP 的功能 公钥密码 数字签名 单向散列函数 证书 压缩 文本数据 大文件的拆分和拼合 13.3 生成密钥对 13.4 加密与解密 13.4.1 加密 生成…

电脑显示丢失mfc140u.dll怎么修复,总共有7个方法

mfc140u.dll 是一个动态链接库&#xff08;Dynamic Link Library&#xff09;文件&#xff0c;它是Microsoft Foundation Class (MFC)库的一部分&#xff0c;专为使用C编程语言开发Windows应用程序而设计。MFC库由微软提供&#xff0c;作为一个高级的应用程序框架&#xff0c;旨…

数据分析——业务指标量化

业务指标量化 前言一、统计指标二、统计指标特点完整的统计指标统计指标的理解和使用方法 三、统计指标类型总量指标时期指标时点指标总量指标的作用 相对指标计划完成相对数指标结构相对数指标比例相对数指标比较相对数指标动态相对数指标 平均指标 四、数量指标和质量指标五、…

【JVM】从硬件层面和应用层面的有序性和可见性,到Java的volatile和synchronized

Java的关键字volatile保证了有序性和可见性&#xff0c;这里我试着从底层开始讲一下有序性和可见性。 一&#xff0c;一致性 数据如果同时被两个cpu读取了&#xff0c;如何保证数据的一致性&#xff1f;或者换句话说&#xff0c;cpu1改了数据&#xff0c;cpu2的数据就成了无效…

Final Draft 12 for Mac:高效专业剧本创作软件

对于剧本创作者来说&#xff0c;一款高效、专业的写作工具是不可或缺的。Final Draft 12 for Mac就是这样一款完美的选择。这款专为Mac用户设计的剧本创作软件&#xff0c;凭借其卓越的性能和丰富的功能&#xff0c;让您的剧本创作更加得心应手。 Final Draft 12支持多种剧本格…

QML及VTK配合构建类MVVM模式DEMO

1 创建QT QUICK项目 这次我们不在主程中加载VTK的几何&#xff1b; 在qml建立的控件&#xff0c;创建MyVtkObject类的单例&#xff0c;main中将指针和单例挂钩&#xff1b; 在MyVtkObject实例中操作 QQuickVTKRenderItem 类即可&#xff1b; 由于VTK的opengl显示是状态机&a…

Bpmn.js使用(仅查看版)

Bpmn.js使用&#xff08;仅查看版&#xff09; 下载 npm install bpmn-js创建一个 Dom 节点来挂载画布元素。 <a-tabs v-model:activeKey"activeKey" change"tabsChange"><a-tab-pane key"1" tab"审批记录"><a-tabl…

保护宝贵的历史财富——博物馆文物管理

文物是一个国家的瑰宝&#xff0c;承载着历史的记忆和文化的传承及精髓。为了保护这些珍贵的文化遗产&#xff0c;仓库管理尤为重要。仓库管理的目的是确保文物的完整性、安全性和可持续保护&#xff0c;并为研究、展览和教育提供支持。 首先&#xff0c;文物仓库管理注重文物的…

前端css中径向渐变(radial-gradient)的使用

前端css中径向渐变的使用 一、前言二、主要内容说明&#xff08;一&#xff09;、径向渐变的形状1.椭圆形渐变&#xff08;ellipse&#xff09;&#xff0c;源码12.源码1运行效果3.圆形渐变&#xff08;circle&#xff09;&#xff0c;源码24.源码2运行效果 &#xff08;二&…

Windows安装RabbitMQ教程(附安装包)

需要两个安装包 Erlang 安装包: https://download.csdn.net/download/Brevity6/89274663 (自己从官网下载也可以) RabbitMQ Windows 安装包&#xff1a; https://download.csdn.net/download/Brevity6/89274667 (自己从官网下载也可以) Erlang安装 Erlang安装傻瓜式下一…

数据结构05:树与二叉树 习题01[C++]

考研笔记整理&#xff0c;本篇作为树与二叉树的基本概念习题&#xff0c;供小伙伴们参考~&#x1f95d;&#x1f95d; 之前的博文链接在此&#xff1a;数据结构05&#xff1a;树与二叉树[C]-CSDN博客~&#x1f95d;&#x1f95d; 第1版&#xff1a;王道书的课后习题~&#x1…

DenseCLIP论文讲解

文章目录 简介方法总体框架 &#xff08;Language-Guided Dense Prediction&#xff09;上下文感知提示 &#xff08;Context-Aware Prompting&#xff09;应用实例 论文&#xff1a;DenseCLIP: Language-Guided Dense Prediction with Context-Aware Prompting 代码&#xff1…

最全软件测试面试问题和回答,适合全文背诵

求职&#xff0c;类似于打仗&#xff0c;是一场挑战自己的战斗&#xff0c;也是一场跟用人单位的博弈&#xff0c;更是一场千人过独木桥的厮杀、混战。《孙子谋攻篇》中早就说了&#xff1a;"知己知彼&#xff0c;百战不殆&#xff1b;不知彼而知己&#xff0c;一胜一负&a…

python数据分析——数据的选择和运算

数据的选择和运算 前言一、数据选择NumPy的数据选择一维数组元素提取示例 多维数组行列选择、区域选择示例 花式索引与布尔值索引布尔索引示例一示例二 花式索引示例一示例二 Pandas数据选择Series数据获取DataFrame数据获取列索引取值示例一示例二 取行方式示例loc() 方法示例…