尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
【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; }
RELATED

相关推荐

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

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

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

📅 2026/10/5 2:28:41
17 大模型的记忆只有“一杯水“,长对话怎么不翻车?

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

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

📅 2026/10/5 2:28:41
【Agent】【workflow】4.纠正性RAG工作流案例

【Agent】【workflow】4.纠正性RAG工作流案例

1. 案例目标 本案例展示了如何使用LlamaIndex工作流实现纠正性RAG(Corrective Retrieval Augmented Generation, CRAG)系统。主要目标包括: 实现一个能够自动评估检索文档相关性的RAG系统当检索到不相关文档时,自动进行查询转换和网络搜索结合本地文档…

📅 2026/10/5 2:23:41
MORE NEWS

更多资讯

📰

C++模块化设计实战:切依赖而非切文件,从接口到信息隐藏

写了六年多的 C,面试过不少候选人,也重构过好几个“改一个功能要加班三小时”的老项目,我越来越觉得 C模块化设计 这四个字被严重低估了。很多人一提模块化就想到“把代码拆成多个文件”,似乎文件拆得越多就越模块化——实际不是这…

📰

RSA签名校验从原理到实战:2048/4096密钥选型与常见坑

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

📰

健身小程序+SSM后端项目实战:从分层架构到前后端联调

1. 项目概述:这个健身小程序到底能做什么健身小程序配上SSM后端,这组合在课设、毕设和练手项目里都属于出镜率特别高的一类。我当初拿到这套源码的时候,第一反应其实挺常见的:“又是一个标准的增删改查项目呗”,但真把…

📰

C++手写红黑树:从旋转变色到STL源码的完整实现

最近在准备给一个学弟讲STL源码,翻到std::map底层那段_Rb_tree的时候,他问我:“这红黑树到底难在哪,为什么网上教程全是‘看图理解’,一到自己写就废?” 我回想了一下自己两年前从C开始写红黑树的过程&…

📰

插件加载机制与排障实战:从原理到设计插件体系

作为一个搞了十几年开发的程序员,我这几年几乎每天都在跟“插件”打交道。尤其是最近,项目里频繁出现failed to load plugins、harness failed to load plugins web boot: 2 entries did not activate这类报错,身边也有不少朋友在问iar plugi…

📰

OpenShell 恢复经典开始菜单教程:Win11/Win10 效率与自定义兼顾

跟你讲实话,Windows那个磁贴式的开始菜单,我从Win8时代骂到了Win10,到了Win11依然没改回正常人该用的样子。微软这些年一直在折腾界面,一会儿把开始菜单变成全屏广告位,一会儿又塞进一堆你用不上的推荐应用&#xff0c…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬