进程的管理与控制详解:创建、终止、阻塞等待与非阻塞等待

news2024/11/14 22:54:57

目录

一、进程创建

1、实例

2、fork函数详解

(1)fork函数模板

(2). fork() 函数的工作原理

(3). fork() 返回值和错误处理

3、如何理解进程创建过程

二、进程终止

1、终止是在做什么?

2、进程终止,有三种情况

3、进程如何终止?

三、进程等待

1、为什么要等待?

2、怎么等待?

(1)wait函数

(2)waitpid函数

四、阻塞等待与非阻塞等待


一、进程创建

1、实例

int main()
{ 
  pid_t pid;
  pid = fork();
  
  if(pid < 0)
  {
    //创建失败
    printf("forkfailed\n");
    return 1;//终止程序,退出码设置为1,以显示错误退出
  }
  else if(pid == 0)
  {
    //子进程

    printf("I am a child process!,chailPID:%d\n",getpid());
  }
  else 
  {
    //父进程,返回值>0 
    printf("I am a father process!,fatherPID:%d,childPID:%d\n",getpid(),pid);
  }

  return 0;
}

2、fork函数详解

(1)fork函数模板

#include <unistd.h>

pid_t fork(void);

fork() 函数返回两次,
一次在父进程中返回子进程的进程 ID (PID),
一次在子进程中返回 0。
如果 fork() 失败,返回一个负值,表示错误。

(2). fork() 函数的工作原理

调用 fork() 函数时,操作系统会创建一个新的进程(子进程),该子进程是调用进程(父进程)的一个副本。
新进程(子进程)会复制父进程的地址空间、代码段、数据段和堆栈等信息,但是它们会有各自独立的内存空间。
子进程的 PID 和父进程不同,但是它们会继承父进程的文件描述符和信号处理器等。
fork() 后,父进程和子进程同时开始执行代码,但是它们执行的顺序和执行的内容可能有所不同,具体取决于操作系统的调度策略。

(3). fork() 返回值和错误处理

如果 fork() 返回值 >  0,则这是在父进程中返回的子进程的 PID。
如果 fork() 返回值等 == 0,则这是在子进程中返回的。
如果 fork() 返回值 <  0,则表示创建新进程失败,可能是因为系统资源不足或者其他错误。

3、如何理解进程创建过程

进程:内核的相关管理数据结构(task_struct mm_struct)+ 页表 + 代码和数据
上述对进程的描述,是从进程具有独立性的角度出发去看待
进程具有独立性,说明有各自的PCB、页表、数据;
而代码虽然是共享的,但是权限是只读的不能修改,因此互不影响

当使用fork创建进程时:
分配新的内存块和内核数据结构给子进程
将父进程部分数据结构内容拷贝给子进程
添加子进程到系统进程列表中
fork返回,开始调度器调度

为什么给父进程返回子进程的PID,给子进程返回0?
前者因为方便父进程对子进程标识的管理
后者因为返回创建成功与否的标志

fork常规用法:子进程执行和父进程类似的任务 / 子进车执行全新的任务

fork调用失败的原因
系统进程太多,资源不够

二、进程终止

1、终止是在做什么?

释放曾经的代码和数据所占据的空间
释放内核数据结构(但是task_struct延后,Z状态的僵尸进程)

2、进程终止,有三种情况

a、代码跑完,结果正确

b、代码跑完,结果不正确
那么,代码跑完,正确不正确,我怎么知道?怎么判断?
可以通过进程的退出码决定

c、代码没有跑完,异常提前退出
如果进程异常,退出码就没有意义
但是,如果出现了异常,我想知道,为什么出现异常?出现了什么异常?
出现什么异常,通过看退出信号是多少判断
进程出现异常,本质是因为进程收到了OS发给进程的信号
例如:kill -9 XXX
这个命令本质是XXX进程收到了OS的信号,为9,就会以killed的形式终止

那么,如何判断进程终止是处于上述三种情况的哪一种?
1、先确认是否异常退出
2、如果不是异常,就说明代码跑完,看退出码

因此,衡量一个进程退出到底是什么情况?
需要两个数字:退出码(跑完) + 退出信号(异常)的组合
而这个退出信息,要给父进程bash知道,确保父进程对子进程的管理
因此,进程的PCB task_struct就会存在两个属性:

int sig_code
int exit_code

在vs编程运行崩溃时,发生了什么?
是因为进程做了不该做的事情,OS杀掉了进程

main函数的返回值是什么意思?

int main()

{

        //...

        return 0;

}

是本进程的退出码,这个退出码交给父进程,让父进程知道子进程退出的情况(成功 / 失败且失败的原因是什么)
退出码为0,表示成功
退出码不为0,表示失败

查看退出码:

echo $?

?这个问号,是父进程bash获取到的,最近一个子进程退出的退出码

返回值返回给谁?返回给父进程bash
这个返回值是退出码,退出码交给bash之后,如果不是0,表示错误
此时bash会通过一定的形式将退出码转化为错误描述,strerrot函数

char* strerrot(int erronum):错误码转化为错误描述

以下是常见错误:

错误码 (errnum)错误描述 (错误码对应的错误描述)
1操作不允许的权限
2系统找不到指定的文件
3系统找不到指定的路径
4系统没有空间供处理此操作
5输入/输出错误
6设备不可用
7存储设备无法访问
8请求的文件描述符超出范围
9文件已经打开
10操作过多的文件系统
11资源暂时不可用
12文件名过长
13权限不足,拒绝访问
14资源暂时不可用,尝试再次

main函数为什么要有返回值?
这是因为本质上,我们自己写的所有进程任务,都是bash的子进程
而子进程的运行状况如何,父进程得知道,便于对子进程的管理
所以,父进程怎么知道子进程的状态呢?通过main函数的返回值判断
所以,main函数返回值的本质,是通知父进程任务执行情况

又为什么返回0?
0表示进程执行成功
非0表示失败,而且用不同的非0数字表示错误的原因类型,每个数字对应一个错误的描述

char* strerrot(int erronum):错误码转化为错误描述

3、进程如何终止?

a、main函数中直接return,表示进程终止(非main函数,return表示函数结束)

b、代码调用exit函数(引起一个正常的进程终止)
参数类似于main函数的return退出码
当调用exit函数时,可以在进程的任意位置退出

c、_exit(终止一个调用进程)
exit和_exit的区别是什么?
区别在于exit在退出时,会刷新缓冲区;_exit不会
exit是C语言库函数;_exit是系统调用
所以,本质上,exit一定会调用_exit系统接口
因为不允许用户直接越过操作系统访问底层的进程数据
所以,我们可以知道,缓冲区是介于系统调用和库函数之间的
也就是说,缓冲区不是操作系统内核缓冲区

三、进程等待

任何进程,在退出的情况下,一般必须要被父进程进行等待
如果退出时,父进程不管不顾,退出进程就会处于Z(僵尸状态),长期如此,就会造成内存泄漏
僵尸状态:进程没有被执行,不在CPU的运行队列,此时操作系统就会回收存在内存中的代码数据,但是不会释放PCB结构体
同时,僵尸进程无法被杀死,因为已经死了的僵尸,不能死两次
具体详情,可以参考博主的其他文章:零基础进程最详解:进程状态、僵尸进程、孤儿进程、阻塞态、挂起态、进程切换、进程常用命令、进程创建、队列优先级_僵尸进程孤儿进程-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_51216031/article/details/140850173?spm=1001.2014.3001.5501

1、为什么要等待?

(1)通过父进程等待,解决子进程退出时的僵尸问题,回收系统资源
(2)获取子进程的退出信息(因为父进程要知道子进程因为什么退出,但是并非必要)

2、怎么等待?

通过wait / waitpid函数

(1)wait函数

wait 函数是一个阻塞式的系统调用,用于暂停父进程的执行,直到一个子进程结束或者收到一个信号为止。一旦子进程终止,wait 函数会获取子进程的终止状态并返回。

pid_t wait (int *status);//返回值是,等待成功时,子进程的pid
status:等待父进程中,任意一个子进程退出,如果不关心子进程的退出状态,可以传入 NULL。

返回值:如果成功,返回终止子进程的进程ID(PID)。
如果出错,返回 -1。

如果子进程没有退出,父进程一直在阻塞等待状态,即S(sleeping)状体
这种阻塞,本质是在等待子进程这个软件状态就绪,即返回信息,再死亡释放子进程

(2)waitpid函数

pid_t waitpid(pid_t pid, int *status, int options);
返回值:当正常返回的时候,返回收集到子进程的进程ID

参数:

第一个参数pid:等待的子进程PID:
< -1:等待进程组ID等于pid绝对值的任何子进程。
-1:等待任何子进程。
0:等待与调用进程在同一进程组的任何子进程。
> 0:等待指定PID的子进程。

第二个参数status:一个整型指针,用于存储子进程的退出状态信息。如果不关心子进程的退出状态,可以传入 NULL。

第三个参数options:指定等待的选项,例如 WNOHANG 可以使 waitpid 成为非阻塞的。

返回值:如果成功,返回终止子进程的进程ID(PID)。
如果出错,返回 -1。

WIFEXITED(status):获取退出码,返回值非0为正常退出,不正常为0

子进程返回的信息,就是通过wait_pid中的参数status获取的
因此,status不能简单视为一个整数
status在32位下,我们只关心低16位
在这16位中,8-15表示退出状态,0-6表示退出信号

低16位的含义:

退出状态:位于低16位的8-15位。这个部分表示子进程的退出状态。通常,如果子进程正常退出,这个状态会是0。
退出信号:位于低16位的0-6位。这部分表示导致子进程终止的信号。如果子进程不是正常退出(比如因为接收到了某个信号而终止),那么这部分会包含有关信号的信息。

四、阻塞等待与非阻塞等待

如果子进程没有退出
此时父进程在执行waitpid进行等待,处于阻塞等待状态
进程阻塞的本质就是进程不在运行调度队列中,状态不为R
如果父进程一直处于阻塞状态,就相当于父进程什么也没有做,就只是在等待子进程的退出
这样不好
那么可不可以让父进程不处于阻塞状态去等待呢?
可以,这种状态叫做非阻塞等待
怎么做?设置函数参数

pid_t waitpid(pid_t pid, int *status, int options);

对于该函数的options参数值设置为WNOHANG值(一个宏)
WNOHANG 是一个宏定义,通常在使用 waitpid 函数时用作参数,用于指定在调用 waitpid 函数时的父进程处于非阻塞等待状态。
具体来说:WNOHANG 的全称是 "Wait No Hang"。
非阻塞等待的时候 + 循环 = 非阻塞轮询
在非阻塞轮询情形下,父进程就可以做其他的事情

如何理解呢?

假设,你有一个女朋友,假设,注意,我说的是假设哈
你在大学谈了一个女朋友
周末你约她出去玩,可是她说他要化妆,要打扮一下
于是你就到她的宿舍楼下等
此时,你和你女朋友的处境就相当于子进程和父进程
你是父进程,你女朋友是子进程

如果在等的期间,你一句话都不敢说,啥也不敢做,
就像一个二棒槌一样杵在楼下等待
那么,此时你这个父进程就相当于阻塞等待状态
啥也没做,就是等,浪费生命,浪费时间

但是,如果你在等的期间,你每隔几分钟打个电话问个情况,说好了没有啊?
如果她告诉你好了,就出发
如果她告诉你没有好,那你也不能像棒槌一样干杵着
所以,你就刷刷抖音,欣赏欣赏风景,做自己的事情
然后再时不时打电话问情况
好了,就出发;没好,就做自己的事情
于是,此时,你和你女朋友的状态,就相当于非阻塞等待状态
打电话相当于一个函数调用,她给你的答复好没好是返回值
你拿到这个返回值当作一个参数,作为参考
返回值为好了,你就结束等待
返回值为没好,你就继续做手头的事情
这就是非阻塞等待状态
同时,你每隔几分钟打一次电话,
这个就叫做轮询
所以,
非阻塞等待的时候 + 循环 = 非阻塞轮询
在非阻塞轮询情形下,父进程就可以做其他的事情

虚拟地址空间是时代技术发展的产物
代码是只读属性,为什么是只读?
因为页表的权限设置只有只读,而我们使用的都是虚拟地址
会被页表部分修改命令被拦截

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

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

相关文章

变电站的瞬态过电压和雷击保护

瞬态过电压是电力系统的典型现象。过电压的来源是直接或附近的雷击、开关操作、电磁脉冲和静电放电。保护变电站设备免受瞬态过电压影响的经典装置是避雷器。 变电站常见的暂态过电压来自于开关操作&#xff0c;可怕的是雷电&#xff0c;它会带来较大的扰动。 雷击引起的瞬态…

ClickHouse 进阶【建表、查询优化】

1、ClickHouse 进阶 因为上一节部署了集群模式&#xff0c;所以需要启动 Zookeeper 和 ck 集群&#xff1b; 1.1、Explain 基本语法 EXPLAIN [AST | SYNTAX | PLAN | PIPELINE] [setting value, ...] SELECT ... [FORMAT ...] AST&#xff1a;用于查看语法树SYNTAX&#…

Moretl 同步设备日志到服务器

使用咨询: 扫码添加QQ 永久免费: Gitee下载最新版本 使用说明: CSDN查看使用说明 功能: 定时(全量采集or增量采集) SCADA,MES等系统采集工控机,办公电脑文件. 优势1: 开箱即用. 解压直接运行.插件集成下载. 优势2: 批管理设备. 配置均在后台配置管理. 优势3: 无人值守 采集端…

注意!!可能这是系统分析师旧教程最后一次考试,赶紧学起来

系统分析师考试是全国计算机技术与软件专业技术资格考试的高级水平考试之一&#xff0c;它是一项专业考试&#xff0c;旨在通过对计算机系统的规划、分析和设计来培养行业内的专业技术人才。近日在国家版本数据中心&#xff0c;查到系统分析师已经有2024最新版的教程出来了&…

JAVA毕业设计156—基于Java+Springboot+vue的电子招投标管理系统(源代码+数据库+万字论文)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootvue的电子招投标管理系统(源代码数据库万字论文)156 一、系统介绍 本项目前后端分离(可以改为ssm版本)&#xff0c;分为供应商、单位、管理员三种角色 1、供应…

PMP报考条件真的需要做项目达到3年时间吗?

很多朋友想报考项目管理资格证书的时候&#xff0c;上网一看报考资格&#xff0c;一般会是这样&#xff1a; 第一类&#xff1a;拥有学士学位或同等学历以下者&#xff0c;申请者必须具备至少7500个小时的项目管理经验&#xff0c;并且在申请之日前8年内&#xff0c;累计项目管…

AI大模型加速落地 “新蓝海”如何开拓

【编者按】 当前&#xff0c;生成式人工智能技术在多个领域展现出广泛的应用潜力&#xff0c;逐渐成为科技领域的关注焦点。 国家互联网信息办公室最新数据显示&#xff0c;截至目前&#xff0c;我国已经完成备案并上线、能为公众提供服务的生成式人工智能服务大模型已达180多…

ABeam 德硕| FY25 Kickoff MeetingDinner 回顾

自律 Self-discipline 7月一整月&#xff0c;ABeam中国各office相继举办了新财年的Kickoff会议。Kickoff意为启动&#xff0c;在这个场合&#xff0c;所有员工将一同参会&#xff0c;作为新财年的启幕仪式。 今年ABeam中国以“自律”作为年度主题&#xff0c;本次全站Kickoff…

Java获取exe文件详细信息:产品名称,产品版本等

使用Maven项目&#xff0c;在pom.xml文件中注入&#xff1a; <dependency><groupId>com.kichik.pecoff4j</groupId><artifactId>pecoff4j</artifactId><version>0.4.1</version></dependency> 程序代码&#xff1a; import …

电脑技巧:9个免费的AI图片无损放大工具和网站

今天小编给大家介绍9款免费的AI图片放大工具和网站&#xff0c;帮助你提高图片清晰度&#xff0c;感兴趣的朋友可以自己试一试&#xff01; 电脑技巧&#xff1a;9个免费的AI图片无损放大工具和网站 美图设计室 美图设计室是美图秀秀公司推出的一款在线图片编辑和设计工具箱&…

基于ESP32的遥控小车

目录 1.ESP32简介 2.项目构思 3.项目所需材料 4.代码示例 5.实物运行 1.ESP32简介 ESP32是一个集成天线和射频巴伦、功率放大器、低噪声放大器、滤波器和电源管理模块。整个解决方案占用的印刷电路板面积最少。该板采用台积电40nm低功耗技术的2.4GHz双模Wi-Fi和蓝牙芯片&…

计算机网络基础 - 计算机网络和因特网(2)

计算机网络基础 计算机网络和因特网Internet 结构和 ISP分组延时、丢失和吞吐量四种分组延时分组丢失吞吐量 协议层次及其服务模型概念数据单元&#xff08;DU&#xff09;协议栈TCP/IP 协议各层次的协议数据单元IOS/OSI 参考模型 计算机网络和因特网的历史早期计算机网路&…

RTSP系列三:RTP协议介绍

RTSP系列&#xff1a; RTSP系列一&#xff1a;RTSP协议介绍-CSDN博客 RTSP系列二&#xff1a;RTSP协议鉴权-CSDN博客 RTSP系列三&#xff1a;RTP协议介绍-CSDN博客 RTSP系列四&#xff1a;RTSP Server/Client实战项目-CSDN博客 目录 一、基本概念 二、RTP报文格式 三、R…

代码随想录训练营 Day21打卡 二叉树 part08 669. 修剪二叉搜索树 108. 将有序数组转换为二叉搜索树 538. 把二叉搜索树转换为累加树

代码随想录训练营 Day21打卡 二叉树 part08 一、 力扣669. 修剪二叉搜索树 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 …

密码学基础:搞懂Hash函数SHA1、SHA-2、SHA3(2)

目录 1.引入 2. SHA512-224\256 3.SHA-3 4.MD5 5.SM3 1.引入 上篇密码学基础&#xff1a;搞懂Hash函数SHA1、SHA-2、SHA3(1)-CSDN博客&#xff0c;我们先就将基础的SHA1\2讲解了&#xff0c;接下来我们继续聊SHA-3、SHA2变体SHA512_224\256等 2. SHA512-224\256 SHA512…

[oeasy]python0028_女性程序员_Eniac_girls_bug_Grace

028_第一个bug是谁发现的_编译之母 回忆上次内容 py文件 是 按照顺序 一行行 挨排 解释执行的 可以用 pdb3 hello.py 来调试程序 顺序执行 程序 在文本中 从上到下 是 一行行写的 解释器 从上到下 是 一行行解释的 调试 也是 从上到下 一行行 调试的 bug这个东西 是什么时候才有…

Rsync未授权访问漏洞

Rsync未授权访问漏洞 Rsync是Liux/Unix下的一个远程数据同步工具&#xff0c;可通过LAN/WAN快速同步多台主机间的文件和目录&#xff0c;默认运行在873端口。由于配置不当&#xff0c;导致任何人可未授权访问Syc,上传本地文件&#xff0c;下载服务器文件。RSyc默认允许匿名访问…

Java—继承和多态 (๑╹◡╹)ノ“““

目录&#xff1a; 一、继承&#xff1a; 为什么面向对象中有继承的概念&#xff1f;那么继承又是什么&#xff0c;继承又有什么作用呢&#xff1f;在我们生活中啊&#xff0c;也存在继承的关系&#xff0c;比如&#xff1a;你父母的财产由你“继承”。那在面向对象中&#xff…

vxe-pulldown 设置了宽度,并不能100%的占满整个容器的解决

1、下拉容器的使用 2、然而&#xff0c;这个宽度的显示是个问题&#xff0c;只占了一小部分&#xff1a; 长度并没有充满整个容器。 vxe-input设置了100%&#xff0c;然后也是一样的效果。 3、解决&#xff1a; .vxe-pulldown {width: 100% !important;} 增加上面的样式&…

本地GitLab runner自动编译Airoha项目

0 Preface/Foreword 1 GitLab runner环境 具体情况如下&#xff1a; Gitlab-ruuner运行在wsl 1中的Ubuntu 18.04 distro上专门为GitLab-runner分配了一个用户&#xff0c;名为gitlab-runner 2 自动编译 2.1 Permission denied 编译过程中&#xff0c;有两个文件出现权限不允…