当前位置: 首页 > web >正文

进程控制(linux)

进程控制

  • 1、进程创建
    • 1.1 fork
      • 写实拷贝
  • 2、进程终止
  • 3、进程等待
    • 3.1 进程等待的必要性
    • 3.2 进程等待的方法
  • 4、进程程序替换

1、进程创建

1.1 fork

在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。

#include <unistd.h>
pid_t fork(void);
返回值:子进程中返回0,父进程返回子进程id,出错返回-1
进程调用fork,当控制转移到内核中的fork代码后,内核做:
》分配新的内存块和内核数据结构给子进程
》将父进程部分数据结构内容拷贝至子进程
》添加子进程到系统进程列表当中
》fork返回,开始调度器调度

fork常规用法
一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请求,生成子进程来处理请求。
一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数。

写实拷贝

在这里插入图片描述
1、之前我们谈过这里父子代码共享,数据不修改,也是共享的,为什么?
数据不一定修改,就算修改大概率也只会修改很小的部分;
2、操作系统怎么知道我们要写时拷贝了?
当程序要创建子进程时,父进程就会将当前页表的执行权限全部改为只读,当子进程数据需要修改时,操作系统就会马上识别到我们当前操作是对只读区域进行修改(触发系统错误),然后系统进行缺页中断进行系统检测,然后系统判断发生写时拷贝,然后系统再申请内存、发生拷贝、、、、
3、上面我们说只改变了一部分数据,那为什么还要重新全部拷贝一份数据?
写入操作!=对目标区域的覆盖操作

在这里插入图片描述

2、进程终止

1、main函数返回值—返回给父进程/系统
2、进程退出码–代码错误原因(不同数字表示不同原因)
在这里插入图片描述

3、退出码可以由系统的退出信息来确定,也可以自定义
4、(语言级别)exit让代码在任何地方结束(进程结束),(系统级别)_exit(两者区别在刷新缓冲区的问题)
exit底层就是_exit
5、我们之前的缓冲区概念是语言级别的,跟操作系统无关—c/c++
在这里插入图片描述

3、进程等待

3.1 进程等待的必要性

1.之前讲过,子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存泄漏。
另外,进程一旦变成僵尸状态,那就刀枪不入,“杀人不眨眼”的kill -9 也无能为力,因为谁也没有办法
杀死一个已经死去的进程。
2.最后,父进程派给子进程的任务完成的如何,我们需要知道。如,子进程运行完成,结果对还是不对,
或者是否正常退出。
3.父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息

3.2 进程等待的方法

wait方法

#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status);
返回值:成功返回被等待进程pid,失败返回-1。
参数:输出型参数,获取子进程退出状态,不关心则可以设置成为NULL

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,子进程存在且正常运行,则进程可能阻塞。
如果不存在该子进程,则立即出错返回。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

获取子进程status

wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充。
如果传递NULL,表示不关心子进程的退出状态信息。
否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程。
status不能简单的当作整形来看待,可以当作位图来看待,具体细节如下图(只研究status低16比特
位):

在这里插入图片描述

知识点
1、假如我们的程序,出现错误出现根本没跑完的情况,例如(1/0等),其实计算机是不怕的,因为操作系统会通过信号干掉这个进程 ----(kill -l 查看所有错误信号)

2、进程退出时会记录自己的退出信号
3、我们只能通过系统调用来获取进程退出信息
4、进程出现异常时,操作系统会使用信号终止进程
5、父进程能够知道子进程,子进程跑没跑完由退出码决定,有没异常由信号决定

阻塞非阻塞的问题

在这里插入图片描述

4、进程程序替换

1、上面我们其实谈论的都是子进程执行父进程的代码,那要是我们想要让子进程执行新的程序呢?这就是进程程序替换
在这里插入图片描述

在这里插入图片描述

2、进程替换本质上是我们使用excel调用,直接将当前进程的代码和数据直接覆盖掉,并且执行替换后的程序,本质上就是加载,所以并没有创建新的进程

3、替换后的程序既然可以是系统命令,那能不能是我们自己的程序呢?

在这里插入图片描述

4、execl成功时没有返回值,当失败时返回-1,所以这一系列函数,一旦出现返回,必定执行失败
5、之前我们说过冯洛伊曼结构中,想要将一个程序运行,就必须将它加载到内存中,也就是将该程序的代码和数据加载到内存,execl的操作本质上就是一个加载的操作
6、我们上面已经知道了当我们使用execl时,该进程的代码和数据就已经全部被替换,那要是我们让子进程去执行execl这一操作,父进程仍然完成自己的操作,例如命令行提示,这不就是一个简单的shell嘛
在这里插入图片描述

7、所以linux下所有的程序,全都是fork+execl来执行的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

http://www.xdnf.cn/news/843.html

相关文章:

  • Tailwind 武林奇谈:bg-blue-400 失效,如何重拾蓝衣神功?
  • CSS零基础入门笔记:狂神版
  • http 文件下载和上传服务
  • Android RK356X TVSettings USB调试开关
  • LabVIEW数据采集与传感系统
  • 【项目管理】成本类计算 笔记
  • 离线安装rabbitmq全流程
  • postman乘法计算,变量赋值
  • EXCEL学习
  • JavaScript性能优化实战(1):性能优化基础与性能分析工具
  • 精益数据分析(11/126):辨别虚荣指标,挖掘数据真价值
  • NoSQL数据库
  • 泰迪智能科技大模型应用平台功能特色优势
  • KUKA机器人不同的安装方式的设置
  • leetcode0130. 被围绕的区域- medium
  • Electron Demo 的快速编译与启动
  • 【Django】设置让局域网内的人访问
  • Spring Batch
  • 重构便携钢琴专业边界丨特伦斯便携钢琴V30Pro定义新一代便携电钢琴
  • StarRocks:一款开源的高性能分析型数据仓库
  • 【PCB绘制】信号完整性准则
  • Linux——信号(2)信号保存与捕捉
  • 使用Matlab工具将RAW文件转化为TXT文件,用于FPGA仿真输入
  • 软件工程(1)
  • Spring MVC 核心注解与文件上传教程
  • 【AI News | 20250421】每日AI进展
  • Containerd与Docker的相爱相杀:容器运行时选型指南
  • 模拟散列表
  • VLA论文精读(十四)PointVLA: Injecting the 3D World into Vision-Language-Action Models
  • unity打包安卓时的签名文件jks转换keystore