【Linux】进程退出
标签Linux 进程控制 exit _exit 退出码 task_struct 进程等待重点回答三个问题父进程为什么要关心子进程怎么退出的进程有哪几种退出方式区别是什么异常终止时退出信息存在哪里一、为什么要关心进程的退出情况子进程也是进程它由父进程创建替父进程执行任务。任务执行得怎么样父进程自然需要知道。进程退出可以分为三种场景代码运行完毕结果正确代码运行完毕结果不正确代码异常终止前两种是代码跑完了结果好坏由退出码决定第三种是代码没跑完要看终止信号。二、类比函数的返回值与进程的退出码函数调用中被调函数通过返回值x86 下放在eax寄存器告诉调用者执行情况比如a()调用b() :b() 中 mov eax, 1 ret a() 中 call b mov 0x123[], eax ; 从 eax 取到返回值进程之间是同样的模式函数世界进程世界callfork execreturnexit / return返回值退出码调用者读取返回值父进程 wait 读取退出码三、进程的三种正常退出方式正常终止可以通过echo $?查看退出码从main返回调用exit调用_exit异常退出CtrlC 等信号终止。3.1 从 main 返回int main() { return 0; // 0 表示成功 }main的返回值通常用来表明程序的执行情况return 0代码跑完结果正确return 非01, 2, 3 ...代码跑完结果不正确不同的值代表不同的出错原因具体含义由程序员约定return n等价于exit(n)因为调用 main 的运行时启动代码会把 main 的返回值当作 exit 的参数。所以第 1 种本质上就是第 2 种。3.2 exit(n)#include stdlib.h void exit(int status);exit是C 库函数依次做三件事执行用户通过atexit或on_exit注册的清理函数 此函数是用户自己写的关闭所有打开的流刷新缓冲区缓冲数据全部写出调用_exit3.3 _exit(n)#include unistd.h void _exit(int status);_exit是系统调用直接进入内核终止进程不执行清理函数不刷新 C 库的缓冲区。status定义了进程的终止状态父进程通过wait获取。说明status 虽然是 int但只有低 8 位能被父进程使用。所以_exit(-1)时终端echo $?看到的是 255exit(257)得到 1257 % 256。3.4 exit 与 _exit 的关系exit 用户态收尾工作 _exit四、核心实验为什么 exit 有输出而 _exit 没有// 实验一 int main() { printf(hello); // 注意没有 \n exit(0); } // 运行结果hello[rootlocalhost linux]#// 实验二 int main() { printf(hello); // 注意没有 \n _exit(0); } // 运行结果[rootlocalhost linux]# 什么都没有原因数据有两个仓库printf并不是直接把字符写到屏幕而是先写进C 库维护的用户态缓冲区之后才刷新到内核、再到屏幕printf ── [C库缓冲区在进程自己的内存里] 刷新 ── 内核 ── 屏幕终端的刷新策略是行缓冲遇到\n、缓冲区满、主动fflush、正常退出时才会刷新。exit退出前先刷新缓冲区字符送出去了所以能看到hello_exit直接结束进程缓冲区属于进程的内存进程一没里面的字符就丢了这也说明这个缓冲区是 C 库的不是操作系统内核的。如果缓冲区在内核里_exit也不会丢数据。原因printf(hello); _exit(0);的结果是hello 丢了。什么情况下数据会随着进程结束而丢失数据放在进程自己的内存里进程一结束这块内存被回收数据就没了。数据放在内核的内存里内核不会因为你的进程结束而消失它会继续把数据送到屏幕或写到文件数据不会丢。所以缓冲区在进程自己的内存里。一个实际坑fork 之后的子进程fork 会把父进程用户态缓冲区里未刷新的内容也复制给子进程。因为子进程没缺页的时候mm_struct也会指向父进程的内存。如果父子进程退出时都调用exit各自都会刷新一次导致同一份内容被打印两遍。因此子进程在 fork 后需要提前退出如 exec 失败后时通常用_exit而不是exit。五、谁在读取退出码echo $?$ ./proc $ echo $? 1./proc这个进程的父进程是 bashbash 通过等待子进程拿到退出码并保存下来echo $?打印的就是最近一个程序进程退出时的退出码注意$?每次都是上一条命令的结果所以连续执行两次echo $?第二次得到的是第一次 echo 本身的退出码 0。六、退出码存在哪里task_struct进程退出时退出信息被记录在进程的 PCB 中Linux 下是task_struct。进程退出后会先变成僵尸状态PCB 保留等待父进程通过wait/waitpid来读取。这也是进程等待必要性的来源之一。七、异常终止时 task_struct 里还有东西吗既然异常终止退出码无意义是不是 task_struct 里什么都没有不是。进程终止时内核会把终止信息统一填入task_struct的exit_code字段只是两种终止方式填的内容不同正常终止: | 15 ...... 8 | 7 | 6 ...... 0 | | 退出码 | 0 | 0 | 被信号杀死: | 15 ...... 8 | 7 | 6 ...... 0 | | 未用 | core dump | 终止信号 |正常退出return / exit / _exit退出码放在第 8~15 位低 7 位为 0被信号杀死终止信号编号放在低 7 位第 7 位是 core dump 标志高 8 位无参考价值所以异常时退出码无意义的准确含义是进程没机会执行return/exit/_exit没有程序员设定的退出码此时应该看的是终止信号。补充task_struct 里还有一个exit_signal字段它表示子进程退出时发给父进程的信号通常是 SIGCHLD和子进程被什么信号杀死不是一回事不要混淆。父进程如何区分两种终止方式wait/waitpid的status参数取出的就是上面这个位图不能当普通整数看int status 0; waitpid(pid, status, 0); if ((status 0x7F) 0) { // 低 7 位为 0正常退出 printf(exit code: %d\n, (status 8) 0xFF); } else { // 低 7 位非 0被信号终止 printf(signal: %d\n, status 0x7F); }标准库提供了等价的宏实际开发中更推荐使用if (WIFEXITED(status)) { printf(exit code: %d\n, WEXITSTATUS(status)); } else { printf(killed by signal: %d\n, WTERMSIG(status)); }八、总结属于执行清理函数刷新缓冲区最终调用returnmain语言层面是是exitexitC 库函数是是_exit_exit系统调用否否内核子进程是父进程派出去干活的父进程需要知道结果三种正常退出方式main 返回 → 本质是 exit → 最终都落到_exitexit 比 _exit 多做用户态收尾清理函数、刷新缓冲区缓冲区在 C 库而非内核退出码 0 表示成功非 0 表示失败只有低 8 位有效数值含义由程序约定bash 是命令的父进程echo $?读取的是上一个进程的退出信息退出信息保存在task_struct中进程退出后以僵尸状态等待父进程读取正常退出看退出码第 8~15 位异常退出看终止信号低 7 位退出码$?不是 errno信号终止在 shell 中显示为128 信号编号

相关新闻

AI模型可解释性实战:分层设计与利益相关者沟通

AI模型可解释性实战:分层设计与利益相关者沟通

最近在好几个技术社区和内部复盘会里,都聊到同一个话题:AI 模型跑通了,效果也不错,但把结果汇报给业务方、管理层甚至监管那边时,总会被追问“为什么它给出这个结论”“依据是什么”“我凭什么相信它”。这不是个别现象…

2026/11/6 16:46:04 阅读更多 →
AI生成PPT总带塑料感?五步打造高级感可编辑PPT

AI生成PPT总带塑料感?五步打造高级感可编辑PPT

1. 为什么AI生成的PPT总有一股“塑料感”1.1 从两个真实场景说起先聊两个我亲身经历的场景。第一个场景:某次给一个创业团队做顾问,创始人兴冲冲地给我看他用AI工具生成的融资路演PPT。打开一看,封面是一张饱和度极高的渐变背景,配…

2026/11/6 8:59:10 阅读更多 →
企微SCRM怎么选?14天实测告诉你

企微SCRM怎么选?14天实测告诉你

市面上SCRM几十款每家都说自己最好功能看起来都差不多到底怎么选?我花了14天实测把坑都踩了一遍今天把结论告诉你📌 先搞清楚:你需要SCRM吗这些情况需要SCRM✅ 客户加到企微后没人管✅ 不知道客户从哪个渠道来的✅ 员工离职客户就丢了✅ 销售…

2026/11/7 3:09:35 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/11/8 1:19:03 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/11/7 12:08:40 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/11/8 1:35:05 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/11/8 1:38:41 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/11/7 12:08:40 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/11/8 1:23:14 阅读更多 →

日新闻

周新闻

月新闻