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

进程控制知识

进程终止

进程退出有三种场景:

1:代码运行完成,正确运行。

2:代码运行完成,但是失败。

3:代码异常终止。

一般来说,我们通过正常的main函数return,或者使用exit()和_exit()都是可以正常的结束进程的。而异常退出的典型例子就是ctrl+c。我们可以通过观察退出码来知道我们的进程到底是成功退出还是失败退出了。通常,我们认为除了0和1以外的都是失败退出。0是最正常的退出,而1是不被允许的访问,常见的退出码如下:

最简单的读取返回值的方法是echo $?。这个命令可以获取上一次执行的命令是否正确,通过下图我们可以发现,当正确返回的时候,他返回了1;当报错了以后,他就返回了错误码。

_exit(status)退出是最底层的退出手段,status是一个int类型的数据,他的低八位可以被父进程读取。所以如果我们写了_exit(-1)时,在终端执⾏$?发现返回值是255.

exit(status)是在_exit(status)的基础上进行升级,他会在exit的基础上增加两个任务:1.执行用户通过 atexit或on_exit定义的清理函数。2. 关闭所有打开的流,所有的缓存数据均被写⼊。然后再调用_exit。

return 是最基础的方法,在子函数中是return给主函数,而在主函数(main)中则是同义为exit(n),n就是错误码。

进程等待

首先,进程等待是什么?为什么要进程等待?

等待的意义

总而言之,进程等待,本质就是为了防止僵尸进程的产生。子死父不管,僵尸进程就来了,内存也就泄露了。父进程需要知道目前子进程的任务完成情况,是否正确完成,是否正确退出。⽗进程通过进程等待的⽅式,回收⼦进程资源,获取⼦进程退出信息

进程等待的方法

1.pid_t wait(int* status);

这是一个比较常规的等待方法,如果成功返回等待,则获得子进程的pid;失败返回就返回-1.status是一个整数指针,他会得到返回的状态,如果不关心,可以用NULL.

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

waitpid是一种升级的方法,他的第一个参数是pid,如果写-1,表示等待所有子进程,就和wait等价了。如果pid>0的话,那就等待与该pid的进程。

第二个参数是status,这个status里面的内容有很多,我们需要使用一些系统的宏函数才好解决。WIFEXITED(status): 若为正常终⽌⼦进程返回的状态,则为真。(查看进程是否是正常退出)WEXITSTATUS(status): 若WIFEXITED⾮零,提取⼦进程退出码。(查看进程的退出码)

第三个参数是options,他是决定是否使用非阻塞的方法。为0的话就就是阻塞等待,为WNOHANG的话就是非阻塞等待。其功能和单片机的中断差不多,但是实现逻辑很不一样。他需要使用轮询的思想,最重要的代码如下,本质上是趁着子进程没挂,自己还闲着这段时间,去疯狂的兼职干其他活。

int status = 0; pid_t ret = 0; do { // 1. 抬头看一眼子进程挂没挂 ret = waitpid(-1, &status, WNOHANG); if (ret == 0) { // 2. ret == 0 说明子进程还在开心地狂奔,还没退出呢 printf("child is running\n"); } // 3. 核心:既然子进程没退,我闲着也是闲着,去把我手头的“临时任务”做一遍 handler(); // 4. 判断条件:只要 ret == 0(没抓到退出的子进程),就必须继续循环,继续轮询! } while (ret == 0);

进程程序替换

fork() 之后,父子各自执行父进程代码的⼀部分如果⼦进程就想执行一个全新的程序呢?进程的程序替换来完成这个功能。程序替换是通过特定的接口,加载磁盘上的⼀个全新的程序(代码和数据),加载到调⽤进程的地址空间中

替换原理

⽤fork创建⼦进程后执行的是和父亲进程相同的程序(但有可能执⾏不同的代码分支),子进程往往要调⽤⼀种 exec 函数以执行另⼀个程序。当进程调用⼀种 exec 函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用 exec 并不创建新进程,所以调用 exec 前后该进程的 id 并未改变。

替换函数

有六种以exec开头的文件,可以用于进程替换,其各有不同的用处,但本质都是执行execv。其中,l(list) : 表示参数采⽤列表。v(vector) :参数⽤数组。p(path) : 有 p 自动搜索环境变量 PATH。e(env) : 表示自己维护环境变量。

#include <unistd.h> int execl(const char *path, const char *arg, ...); int execlp(const char *file, const char *arg, ...); int execle(const char *path, const char *arg, ...,char *const envp[]); int execv(const char *path, char *const argv[]); int execvp(const char *file, char *const argv[]); int execve(const char *path, char *const argv[], char *const envp[]);
#include <unistd.h> int main() { char *const argv[] = {"ps", "-ef", NULL}; char *const envp[] = {"PATH=/bin:/usr/bin", "TERM=console", NULL}; execl("/bin/ps", "ps", "-ef", NULL); // 带p的,可以使⽤环境变量PATH,⽆需写全路径 execlp("ps", "ps", "-ef", NULL); // 带e的,需要⾃⼰组装环境变量 execle("ps", "ps", "-ef", NULL, envp); execv("/bin/ps", argv); // 带p的,可以使⽤环境变量PATH,⽆需写全路径 execvp("ps", argv); // 带e的,需要⾃⼰组装环境变量 execve("/bin/ps", argv, envp); exit(0); }



http://www.rkmt.cn/news/1486680.html

相关文章:

  • 051、蓝玻璃滤光片与红外污染:ISP 红外补偿算法与硬件 IRCF 的协同设计
  • Overleaf新手必看:从编译报错到PDF空白,5个LaTeX常见坑的保姆级解法
  • Unbuntu配置SSH服务+RustDesk远程桌面
  • 免费开源小说下载器:100+网站智能抓取,打造你的数字图书馆
  • Cortex-M33微控制器CoreMark性能基准测试移植与优化实战指南
  • i.MX 8ULP低功耗设计:硬件级GPIO状态保持原理与实现
  • 2026年中盘点:国内外十大AI大模型全能横评,谁才是真正的“六边形战士“?
  • 【Kafka源码解读和使用指南】第11篇:KafkaProducer源码全景图——一条消息的奇幻旅程
  • 音乐格式枷锁的终结者:浏览器端音乐解密技术深度解析
  • Cadence XOS内核实战:i.MX RT600 DSP多线程同步机制详解
  • 从S32K1到S32K3:汽车MCU平台迁移的架构变革与实战指南
  • 告别手动抓狂!高效排查Protege Cellfie导入Excel数据错误的3个实用脚本
  • 2026国产红外测油仪热门推荐:品牌技术测评与产业适配分析 - 水质分析仪器---高工
  • 告别IE!用tkwebview2在Python桌面应用中嵌入现代网页(附完整避坑指南)
  • 嵌入式DMA技术深度解析:从原理到实战应用与避坑指南
  • MPC8245与CF卡True IDE模式接口设计:时序匹配与握手模式实战
  • Apollo 配置中心非 Java 客户端实战:Python / Go / Node.js 本地服务如何远程读取配置
  • Windows端口转发终极管理工具:PortProxyGUI完全指南
  • 企业官网的安全架构:从 HTTPS、WAF 到备份与应急响应的 7 层防御工程
  • MATLAB一键绘制多温度黑体辐射光谱图(含300K–6000K普朗克曲线)
  • V/Hz闭环电机控制:从原理到嵌入式软件实现与调试
  • 雄县邦讯商贸:延庆羽绒被回收选哪家 - LYL仔仔
  • MC68SZ328 USB设备驱动开发:从硬件连接到数据传输的完整实践指南
  • 别再手动写报表了!用Stimulsoft.Reports.js + Vue CLI 5分钟搞定数据可视化
  • ComfyUI-FramePackWrapper:8GB显存流畅生成AI视频的终极指南
  • SC140 DSP非侵入式高精度性能测量:EOnCE硬件秒表计时器实战
  • ViGEmBus虚拟游戏控制器驱动:终极完整指南与安装教程
  • MIFARE Ultralight AES安全芯片:低成本应用的AES-128与CMAC实战指南
  • 69.x的平方根
  • Motorola 8位MCU SDK:硬件抽象与静态配置的嵌入式开发实践