【Linux】进程的终止、等待
目录退出码用 strerror 查看退出码描述exit和_exit进程等待概念进程等待的必要性进程等待的方式——两个接口wait函数waitpid函数获取子进程status扩展父进程获取子进程的信息流程waitpid的方法option的非阻塞理解写代码的时候编译后一般会有三种结果程序正常且结果正确程序正常但结果错误程序异常错误示例#include stdio.h int main() { printf(hello world\n); return 0; }写代码的时候通常会在main函数的最后面写一个return 0,这个表示的是程序的执行情况——无异常。如果返回值非0且不同代表他的错误情况不同。其中这个返回值就是退出码这个返回值给谁的——父进程一般是bash写到take_struct内部的父进程要得到子进程的运行情况是从子进程的PCB里面读打印最近一个进程的进程退出码echo $?退出码Linux常见的退出码退出码含义典型场景0成功执行命令正常完成1通用错误一般性错误2命令或参数使用不当参数错误、用法错误126权限被拒绝文件没有执行权限127未找到命令命令不存在或 PATH 错误128n被信号终止n 是信号编号130被 SIGINT 终止CtrlC 中断143被 SIGTERM 终止默认终止信号255退出码超出范围重新计算取模规则规则说明0成功非 0失败范围0~255超过 255 会取模查看echo $?用 strerror 查看退出码描述#include stdio.h #include string.h int main() { for (int i 0; i 10; i) { printf(退出码 %d: %s\n, i, strerror(i)); } return 0; }如果在shell上面想把错误信息打印出来#include stdio.h #include string.h #include errno.h int main() { FILE *fp fopen(notexist.txt, r); if (fp NULL) { printf(错误%s\n, strerror(errno)); } return 0; }exit和_exitexit正常结束进程释放资源把退出码告诉父进程。#include stdio.h #include stdlib.h int main() { printf(hello); // 注意没有 \n exit(0); return 0; } //hello_exit#include stdio.h #include unistd.h int main() { printf(hello); // 注意没有 \n _exit(0); return 0; } //什么都不打印_exit不刷新缓冲区hello留在缓冲区里进程直接退出数据丢失。exit_exit刷新缓冲区会不会执行清理函数会不会关闭流会不会谁提供C 标准库系统调用头文件stdlib.hunistd.h缓冲区内存区域临时存放数据如果遇到\n程序结束、缓冲区满才会输出数据。其中这里面的缓存区是在C语言的库里面的缓存区不是操作系统的。从系统层级角度——exit的底层是封装了_exit_exit是系统调用的exit是库函数的我们知道只有操作系统能管理进程你要结束进程的话就要必须通过操作系统的接口——_exitexit才能做到进一步的结束进程。进程等待概念父进程等子进程退出然后回收子进程的资源、获取子进程的退出结果。进程等待的必要性1、回收子进程资源防止僵尸进程2、获取子进程的退出结果成功还是失败、退出码是多少3、保证父进程和子进程的时序父进程等子进程先退出进程等待的方式——两个接口wait函数#include sys/types.h #include sys/wait.h pid_t wait(int *status);status参数输出型参数记录子进程退出信息传NULL表示不关心退出状态返回值含义 0成功返回被回收子进程的 PID-1失败没有子进程waitpid函数#include sys/types.h #include sys/wait.h pid_t waitpid(pid_t pid, int *status, int options);参数说明pid指定等待哪个子进程status输出型参数记录退出信息options选项0 表示阻塞WNOHANG表示非阻塞Pid的值值含义-1等待任意子进程等价于wait 0等待指定 PID 的子进程0等待同组的任意子进程 -1等待指定进程组的任意子进程options的取值值含义0阻塞等待WNOHANG非阻塞没有子进程退出就立即返回 0返回值返回值含义 0成功返回被回收子进程的 PID0设置了WNOHANG但没有子进程退出-1失败#include stdio.h #include stdlib.h #include unistd.h #include sys/wait.h int main() { pid_t id fork(); if (id 0) { printf(child: pid%d\n, getpid()); sleep(3); exit(10); } else { int status; pid_t ret waitpid(id, status, 0); // 等待指定子进程 printf(parent: waitpid returned %d\n, ret); if (WIFEXITED(status)) { printf(child exit code: %d\n, WEXITSTATUS(status)); } } return 0; }获取子进程statusstatus要看成一个位图来看待。status是一个32 位整数但只有低 16 位有意义。分两种情况正常终止高 8 位是退出码低 8 位是 0被信号终止低 7 位是信号编号第 7 位是 core dump 标志——这样退出码没有意义了获取退出码——用到了位操作#include stdio.h #include errno.h #include string.h #include stdlib.h #include unistd.h #include sys/types.h #include sys/wait.h int exitcode 0; int main() { pid_t id fork(); if (id 0) { // 子进程 int cnt 3; while (cnt) { printf(我是一个子进程, pid : %d, ppid : %d\n, getpid(), getppid()); sleep(1); cnt--; } exitcode 10; exit(10); } // 父进程 // 1. 子进程退出 // 2. 子进程没退出呢 // pid_t rid wait(NULL); int status 0; pid_t rid waitpid(id, status, 0); if (rid 0) { printf(wait success, rid: %d, exit code: %d\n, rid, (status 8) 0xFF); // 获取退出码 } else { printf(wait failed: %d: %s\n, errno, strerror(errno)); } }信号编号这里有熟悉的kill -9 pid,其中这里的9就是杀掉进程的信号编号。——SIGKILL就是宏。简单提一下。扩展父进程获取子进程的信息流程由于进程具有独立性父进程不可能直接得到子进程的退出信息——退出码、状态等。因此要通过系统调用——那么系统调用的得到的子进程的信息又从哪里来——take_struct1. 子进程退出 - 调用 exit(10) - OS 把 exit_code 10、exit_signal 0 存入子进程的 task_struct - 子进程变成僵尸Z2. 父进程调用 waitpid(status) - OS 检查子进程是否已退出 - 已退出 → 从子进程的 task_struct 读 exit_code 和 exit_signal - 把 exit_code 左移 8 位加上 exit_signal - 得到 status 10 8 0x0A00 - 把 status 写入父进程的变量 - 释放子进程的 task_struct - waitpid 返回子进程 PID3. 父进程解析 status - WIFEXITED(status) → 真正常退出 - WEXITSTATUS(status) → 10take_struct的信息struct task_struct { pid_t pid; // 进程 ID long state; // 进程状态Z 表示僵尸 int exit_code; // 退出码 int exit_signal; // 终止信号 // ... };waitpid的方法pid_ t waitpid(pid_t pid, int *status, int options); 返回值 当正常返回的时候waitpid返回收集到的⼦进程的进程ID 如果设置了选项WNOHANG,⽽调⽤中waitpid发现没有已退出的⼦进程可收集,则返回0 如果调⽤中出错,则返回-1,这时errno会被设置成相应的值以指⽰错误所在 参数 pid Pid-1,等待任⼀个⼦进程。与wait等效。 Pid0.等待其进程ID与pid相等的⼦进程。 status: 输出型参数 WIFEXITED(status): 若为正常终⽌⼦进程返回的状态则为真。查看进程 是否是正常退出 WEXITSTATUS(status): 若WIFEXITED⾮零提取⼦进程退出码。查看进程 的退出码 options:默认为0表⽰阻塞等待 WNOHANG: 若pid指定的⼦进程没有结束则waitpid()函数返回0不予以等 待。若正常结束则返回该⼦进程的ID。如果子进程已经退出调用wait/waitpid时wait/waitpid会立即返回并且释放资源获得子进程退出信息。如果在任意时刻调用wait/waitpid子进程存在且正常运行则进程可能阻塞。如果不存在该子进程则立即出错返回option的非阻塞理解int status; waitpid(-1, status, 0); // 0 表示阻塞方式一句话阻塞父进程暂停一直等子进程退出非阻塞父进程不暂停问一下就走过会儿再来问#include stdio.h #include stdlib.h #include unistd.h #include sys/wait.h int main() { pid_t id fork(); if (id 0) { // 子进程 printf(child: 我在干活\n); sleep(5); exit(10); } else { // 父进程 int status; while (1) { pid_t ret waitpid(id, status, WNOHANG); if (ret 0) { // 子进程退出了 printf(child exit code: %d\n, WEXITSTATUS(status)); break; } else if (ret 0) { // 子进程还在运行 printf(parent: 子进程还在跑我先干点别的\n); sleep(1); } } } return 0; }

相关新闻

2026支持蒙古语歌曲的AI音乐工具推荐

2026支持蒙古语歌曲的AI音乐工具推荐

支持蒙古语歌曲的AI音乐工具,重点不只是“输入蒙古语后能出声”,而是歌词发音、长短音、断句、旋律适配和民族音乐氛围能否同时成立。MELO音乐对蒙古语等民族语言进行了针对性优化,并支持马头琴、民族打击乐、长调氛围与现代流行编曲结合&…

2026/10/5 2:28:37 阅读更多 →
17 大模型的记忆只有“一杯水“,长对话怎么不翻车?

17 大模型的记忆只有“一杯水“,长对话怎么不翻车?

面试官翻着简历:"你做过 AI 客服?"候选人点头:"对,知识库问答 多轮对话。""用户跟 AI 聊了 20 轮之后,AI 还记不记得第一轮说了什么?""……应该记得吧?&qu…

2026/10/5 2:28:37 阅读更多 →
如何在 Java 中使用 Selenium 绕过 CAPTCHA

如何在 Java 中使用 Selenium 绕过 CAPTCHA

我发现了一些技巧,可以在自动化操作时减少处理 CAPTCHA 的麻烦。无论是使用 Selenium 还是其他工具,这些策略都能提高你越过这道障碍的机会。目标并不是破解系统,而是在涉及 CAPTCHA 时,让自动化变得不那么复杂、耗时。让我们深入…

2026/10/5 2:27:37 阅读更多 →

最新新闻

专科生写论文必备:8个亲测有效的AI工具清单

专科生写论文必备:8个亲测有效的AI工具清单

写这篇推荐的时候,我其实挺有感触的。我自己是专科出身,当年写毕业论文的时候是真的头疼。不是不努力,是没方法。选题不知道怎么选,文献看了就困,写出来的东西自己都觉得像流水账,改到第三稿的时候连导师都…

2026/10/5 3:01:49 阅读更多 →
AI写论文避坑指南:8款免费工具组合把AIGC率压到8%

AI写论文避坑指南:8款免费工具组合把AIGC率压到8%

又到论文季了。写论文这件事,如今早就不是“闷头敲键盘”的旧模式了,用AI打辅助已经成了很多人的默认操作。但踩过坑的人都知道,AI最擅长的不只是帮你写,更是“面不改色地编”。你让它列参考文献,它给你列得漂漂亮亮、…

2026/10/5 3:01:49 阅读更多 →
基于Flink构建日志实时分析系统:架构、实战与踩坑总结

基于Flink构建日志实时分析系统:架构、实战与踩坑总结

说到日志实时分析,我最深的记忆来自一次差点翻车的线上排查。业务量在一周内翻了三倍,日志从每天几百G涨到了几个T。以前出问题,我们习惯登录服务器用 grep 一条条追,虽然慢但至少能定位;后来那套打法彻底失灵了——一…

2026/10/5 3:01:49 阅读更多 →
Flink日志实时分析平台架构设计与踩坑实战

Flink日志实时分析平台架构设计与踩坑实战

做日志实时分析,大部分人第一反应是ELK那一套,但等数据量真的冲到几十亿条一天、业务方又开始要分钟级聚合报表的时候,Elasticsearch那套全文检索加简单聚合的逻辑就不太够用了。我前两年负责过一套日志分析平台,每天接入的业务日…

2026/10/5 3:01:49 阅读更多 →
Renesas定时器输入捕获实战:从原理到代码精准测量PWM频率与占空比

Renesas定时器输入捕获实战:从原理到代码精准测量PWM频率与占空比

1. 输入捕获方案选型:为什么是定时器而不是软件计时1.1 输入捕获的硬件原理拆解做电机驱动那段时间,我被转速反馈折腾惨了。客户那边过来的转速信号是一路PWM,频率随转速变化,还带着不小的毛刺。最开始图省事,用外部中…

2026/10/5 3:01:49 阅读更多 →
RK3568 MIPI转LVDS桥接GM8775C调试实战指南

RK3568 MIPI转LVDS桥接GM8775C调试实战指南

前阵子在一个项目里,需要把一块老的10.1寸LVDS工业屏挂到RK3568主板上。主板原生显示接口只有MIPI DSI,屏端却是标准的双通道LVDS,中间只能加一颗GM8775C把MIPI信号桥接成LVDS。整个过程前后折腾了差不多三天,把背光不亮、花屏、偏…

2026/10/5 3:00:49 阅读更多 →

日新闻

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 0:00:22 阅读更多 →
AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

1. 从“plugins”这个词说起:它到底在解决什么问题如果你最近在折腾 AI 编程工具,尤其是 Cursor、Codex CLI、Claude Code 这类带 CLI 的编辑器或命令行助手,那你大概率绕不开一个词——plugins。这个词本身不新鲜,从浏览器到 IDE…

2026/10/5 0:00:23 阅读更多 →
第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 0:00:23 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 1:10:22 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 11:40:45 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 9:43:54 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 20:14:29 阅读更多 →