linux-----进程控制

devtools/2024/9/23 9:58:30/
提示:以下是本篇文章正文内容,下面案例可供参考

一、fork()函数

返回值:子进程返回0,父进程返回子进程的id,出错就返回-1.

 fork创建子进程,如果父子一方发生写入时,就会发生写实拷贝,操作系统就会重新申请空间,发生拷贝,修改页表,构建新的虚拟到物理的映射关系。

发生写实拷贝的过程中是怎么样的,fork创建子进程时,操作系统会把父进程的页表项都改为只读,子进程拷贝了一份父进程的页表,发生写入时,由于页表项都是只读的权限,就会因为权限问题出错,这时操作系统就会介入,查看是什么原因出错,例如栈堆区的数据发生修改等,由于这个地方的数据原来就是可读可写的,那么就会发生写实拷贝,重新申请空间,构建虚拟到物理的映射,如果是由于只读常量区发生修改,这个地方本来就是可读不可写的,那么程序就会出错。

我们可以创建多个进程来帮我们执行任务:记得让父进程等待子进程,子进程退出了,它的数据和内存就释放了,不过管理这个进程的PCB还没有释放,就会有大量的僵尸进程,消耗系统内存资源,变卡。

二、进程的中止

1.进程的退出方法

除了main函数return可以退出,还有exit和_exit.它两之间还是有区别的 。exit库函数封装了_exit.exit是库函数而_exit是系统调用。mian函数返回时也会调用了exit.所有也会刷新缓冲区的数据

exit会刷新缓冲区,而_exit不会刷新。

这里我们可以预想一下,其实输出输出都有缓冲区,一般输出时带个\n就会刷新缓冲区,还有就是main函数return返回时也会刷新缓冲区,可是_exit是系统系统调用,exit是函数调用,说明这个缓冲区不是内核缓冲区。 

验证:先不让父进程退出。第一个子进程应该是休眠十秒后,刷新缓冲区,显示打印的结果,而不是打印时直接显示到屏幕上。第二个由于没有休眠return直接刷新缓冲区。结果应该是“hello _exit”休眠十秒后显示第一个子进程要打印的内容。

2.进程退出码和错误码

错误码:这个是在c语言中,是个全局变量。如果库函数调用出错,那么就会把错误码设置,我们要知道错误的原因可以使用strerror打印。这里我们打印了0-9错误码的代表的含义

进程退出码:是进程退出也就是main函数的返回值(注意区分函数中的return),在bash中我们可以拿到最近一次程序的退出码,通过命令获取:echo $?。(echo命令也是个程序,bash通过创建子进程来执行的)。

一个程序退出一共有三种状态,代码跑完,结果正确,代码跑完,结果不正确,程序异常中止,代码没跑完。通过退出码获取进程执行的结果

退出码为0,代表程序没出错,跑完了。一般退出码非0,代表程序出问题了,非0的情况一般分为两种,我们自己定义的退出码,还有一种是操作系统对进程发出信号中止进程的退出码,比如除零错误。我们还可以根据自己的需求自己定义退出码,根据退出码打印原因。    

这个由于除零异常,操作系统直接发信号给进程,提前退出了。bash是父进程,

通过创建子进程来执行./a.out.bash拿到子进程的退出码,然后解释退出的原因。 

进程异常退出是收到了信号,我们可以给进程发信号,即使这个程序是正常运行的。我们给进程发个浮点数异常的信号(8号信号SIGFPE)。

总结:一个程序出异常肯定是收到了操作系统给进程发出的信号,如果没出异常代码跑完了,那么我们可以通过进程的退出码,来判断程序的执行的结果的状态,结果是否符合我们的预想。

3.进程等待

(1)wait()

 等待父进程的任意一个子进程的退出。就是父进程哪个子进程先退出,就等待哪个。

(2)waitpid()

第二个函数的第一个参数是子进程的pid,指定等待哪个子进程退出。int* wstatus是个输出型参数,通过它可以拿到进程的退出码,第三个参数是设置是否堵塞式等待。注意的是,如果options为零,它是个堵塞式等待函数,只有等待成功(条件:子进程退出状态为僵尸)函数返回值为被等待的子进程的pid,才会向下执行,如果options不为零,就是非堵塞式等待了。

大多情况下下,我们使用这个非堵塞式等待,如果刚好子进程退出了,那么它的返回值为子进程的pid,如果子进程没退出(条件没具备:子进程没退出,状态不是僵尸)函数返回值为0,如果返回值小于0说明等待失败了。要注意的是,不管有没有等待成功(返回值为0或者为子进程的pid),它都会向下执行父进程的代码,不会堵塞式等待成功后,才去执行后面的代码。

这里我们用非堵塞式等待

如何等待一批进程然后进行回收。一种是记录子进程的pid,然后根据子进程的数量,一个个等待。

不过我们一般不知道哪个进程先退出,效率不高。直接将waitpid的第一个参数设为-1. 表示等待任意一个进程退出,这个和wait比较像。

 ​​​​​​​

4.如何获取进程的status

status是个int类型的参数,通过函数调用拿到进程PCB中status,不过我们主要看后面的低16位,它可以记录退出码和退出信号。进程退出时或者中止时,操作系统会通过这个进程PCB中status,记录退出码或者收到的信号,同时将进程状态修改为僵尸。

如果进程正常终止后八位无意义,进程异常中止前8位无意义。

我们可以通过等待函数的输出型参数拿到这个数字,获取进程退出的状态。

当然我们直接通过宏来直接获取子进程的退出码

 


http://www.ppmy.cn/devtools/115944.html

相关文章

leetcode 四数相加||

1.题目要求: 给你四个整数数组 nums1、nums2、nums3 和 nums4 &#xff0c;数组长度都是 n &#xff0c;请你计算有多少个元组 (i, j, k, l) 能满足&#xff1a;0 < i, j, k, l < n nums1[i] nums2[j] nums3[k] nums4[l] 0示例 1&#xff1a;输入&#xff1a;nums1 …

Git:版本控制工具介绍

目录 全文概要版本控制工具介绍版本控制系统的概念**版本控制系统的历史****版本控制系统的分类****本地版本控制系统****集中式版本控制****分布式版本控制系统** Git 介绍Git 概念Git 与 SVN 对比**SVN的记录方式****Git 的记录快照** Git 安装Git 安装Bash、CMD与GUIGit 的配…

容器技术--Docker常用命令

Docker常用命令 镜像的命令 # 查看本地所有镜像 docker images # 向服务端发送请求,服务端处理 # 只获取镜像id docker images -q # 镜像管理 docker image# 查看镜像的详细信息 docker image inspect 镜像id # 查看 容器整体信息 docker info | grep -iE

Matlab求解微分方程(解析解与数值解)

matlab求解微分方程解析解和数值解 Matlab求微分方程解析解例题1例题2例题3 Matlab求微分方程数值解一阶微分方程例题一例题二 高阶微分方程例题 Matlab求微分方程解析解 dsolve(eqns,conds,options) eqns:微分方程&#xff08;组&#xff09;、conds&#xff1a;初值条件、opt…

Mybatis 控制台打印sql语句

logging:level:com.cjxjy.device.mapper: debugcom.cjxjy.fault.mapper: debug

探索 ShellGPT:终端中的 AI 助手

文章目录 探索 ShellGPT&#xff1a;终端中的 AI 助手背景介绍ShellGPT 是什么&#xff1f;如何安装 ShellGPT&#xff1f;简单的库函数使用方法场景应用常见问题及解决方案总结 探索 ShellGPT&#xff1a;终端中的 AI 助手 背景介绍 在当今快速发展的技术领域&#xff0c;命…

校园美食发现:Spring Boot技术的美食社交平台

第五章 软件测试 测试存在于软件开发进程中的最后一个阶段&#xff0c;它可以保证一个软件的开发质量是否符合设计者的初衷&#xff0c;也为程序的正式上线做了最后一道质量检测的工序。软件测试主要是控制各种条件、包括软件输出方式&#xff0c;使用模式和运行环境等&#xf…

环球团队快速崛起,掌握最新市场趋势引领未来

近日&#xff0c;一个名为“环球团队”的股票投资团队在业内迅速崭露头角&#xff0c;备受瞩目。该团队由多位在金融证券领域经验丰富、见解独到的专家组成&#xff0c;很快赢得了投资者的信任和支持。他们凭借精准的市场分析和高效的投资策略&#xff0c;多次成功抓住市场机遇…