Linux系统:进程终止的概念与相关接口函数(_exit,exit,atexit)
本节目标
- 理解进程终止的概念
- 理解退出状态码的概念以及使用方法
- 掌握_exit与exit函数的用法以及区别
- atexit函数注册终止时执行的函数
- 相关宏
一、进程终止
进程终止(Process Termination)是指操作系统结束一个进程的执行,回收其占用的资源(如内存、文件描述符等)的过程。它是操作系统管理进程生命周期的重要环节,确保系统资源的有效利用和稳定性。
1.1 进程退出的场景
正常终止
- 程序执行完成:进程完成了其预定的任务,如计算完成、文件处理完毕等。
- 显式调用终止函数:程序通过调用系统提供的终止函数(如
exit()、_Exit()或return)主动请求终止。
异常终止
- 运行错误:如除以零、访问非法内存地址等。
- 信号触发:操作系统或用户通过发送信号(如
SIGKILL、SIGTERM)强制终止进程。 - 资源耗尽:如内存不足、文件描述符耗尽等。
外部干预
- 用户手动终止:通过任务管理器或命令行工具(如
kill)强制结束进程。 - 系统策略:如系统资源紧张时,操作系统可能终止低优先级进程。
1.2 退出码
退出状态码是操作系统或程序用于指示进程执行结果的一种数值标识。它通常是一个整数,用于向调用者(如父进程、脚本或终端)传递进程的执行状态或错误信息。
1.2.1 常见的退出码
| 退出码 | 含义 |
|---|---|
0 | 成功执行,无错误。 |
1 | 通用错误,未具体分类。 |
2 | 误用 shell 内置命令(如 cd 命令在脚本中直接使用但未生效)。 |
126 | 命令找到但无法执行(如权限不足或文件不可执行)。 |
127 | 命令未找到(如拼写错误或路径未包含在 $PATH 中)。 |
128+N | 进程因信号 N 终止。例如: |
- 128+2 (130):SIGINT(通常是 Ctrl+C 中断)。 | |
- 128+9 (137):SIGKILL(被强制终止)。 | |
- 128+15 (143):SIGTERM(正常终止请求)。 | |
>255 | 某些系统可能将状态码截断为 8 位(即取模 256)。例如,exit(257) 返回 1。 |
退出码为0表示命令执行无误,这是完成命令的理想状态。
退出码为1我们也可以理解为“不被允许的操作”,例如没有sodo的权限下使用yum;在例如除 以0等操作也会返回错误码1。
1.2.2 strerror函数
功能:strerror 函数是 C 标准库中的一个函数,用于将错误码转换为描述该错误的字符串。通常用于处理系统调用或库函数返回的错误码,以提供更可读的错误信息。
函数原型:
#include <string.h>char *strerror(int errnum);
其中errnum表示一个整数及错误码,返回值是一个指向描述该错误的字符串的指针。
代码示例:
#include<stdio.h>
#include<string.h>
int main()
{for(int i=0;i<200;i++){//打印0-199所有错误码所对应的错误信息char* err=strerror(i);printf("%d--->%s\n",i,err);}return 0;
}
运行结果:

这里特别要注意的是, 当传入的错误码无法识别的时候strerror函数就会返回一个“Unknown error”的字符串。

1.3 exit与_exit
1.3.1 exit函数
exit函数是 C 和 C++ 标准库中的一个重要函数,用于终止程序的执行,并返回一个退出状态码给父进程或操作系统。操作系统或父进程可以通过退出状态码来判断程序的执行结果。
函数原型:
在C语言中exit的函数原型通常定义在<stdlib.h>中
#include <stdlib.h>void exit(int status);
在 C++ 中,也可以使用 C 风格的 exit 函数,或者使用 C++ 标准库中的std::exit函数,定义在<cstdlib.h>头文件中:
#include <cstdlib>void std::exit(int status);
参数解析:
status:一个整数表示程序退出的退出状态码
0 通常表示程序成功执行。
非零值表示程序执行失败或出现错误。
具体的非零值可以由开发者定义,以表示不同类型的错误。
函数行为:
调用exit函数时会立即终止程序的执行,并返回控制权给操作系统。
在退出之前exit函数会执行以下清理操作:
- 调用所有已注册的
atexit函数(通过atexit函数注册的清理函数)。 - 刷新所有打开的输出流/缓冲区。
代码示例:
#include <stdio.h>
#include <stdlib.h>void cleanup() {printf("Performing cleanup operations...\n");
}int main() {// 注册一个清理函数if (atexit(cleanup) != 0) {fprintf(stderr, "Could not register cleanup function\n");return EXIT_FAILURE; // 使用 EXIT_FAILURE 表示失败}// 程序逻辑printf("Program is running...\n");// 模拟错误情况,退出程序int error_code = 1; // 自定义错误码printf("An error occurred. Exiting with code %d\n", error_code);exit(error_code);// 下面的代码不会被执行return 0;
}
注意事项:
调用exit函数时程序会立即终止执行,后续的代码不会执行。如果想要在退出之前执行某些清理操作应该提前使用atexit函数将指定的函数注册到程序的退出处理列表中。
1.3.2 _exit函数
_exit 函数是一个用于立即终止程序执行的底层系统调用。它通常在需要快速终止进程而不执行正常的清理操作(如调用退出处理程序、刷新缓冲区或关闭文件描述符)时使用。
函数原型:
#include <unistd.h>void _exit(int status);
参数解析:
status:一个整数表示程序退出的退出状态码
0 通常表示程序成功执行。
非零值表示程序执行失败或出现错误。
具体的非零值可以由开发者定义,以表示不同类型的错误。
注意事项:
_exit 不会调用通过 atexit 注册的函数,也不会刷新标准 I/O 缓冲区。这意味着任何未写入的数据可能会丢失。
使用 _exit 终止进程时,文件描述符不会自动关闭。这可能导致资源泄漏,除非父进程负责清理。
1.3.3 exit与_exit函数的区别
| 特性 | exit | _exit |
|---|---|---|
| 定义 | C 标准库函数 | 底层系统调用 |
| 头文件 | <stdlib.h> | <unistd.h> |
| 清理操作 | 执行清理操作 | 不执行任何清理操作 |
| 缓冲区刷新 | 刷新所有标准 I/O 缓冲区 | 不刷新缓冲区 |
| 文件描述符 | 通常关闭所有打开的文件描述符 | 不关闭文件描述符 |
| 退出状态 | 传递退出状态给操作系统 | 传递退出状态给操作系统 |
| 使用场景 | 正常终止程序 | 异常终止程序或避免清理操作 |
缓冲区处理示例:
exit函数在终止程序之前会刷新所有缓冲区:
#include<stdio.h>
#include<stdlib.h>
int main()
{printf("这是一个示例");exit(0);return 0;
}
运行结果:
![]()
_exit不会执行任何清理操作,也不会刷新缓冲区:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{printf("这是一个示例");_exit(0);return 0;
}

1.4 atexit函数
是 C 标准库中的一个函数,用于注册程序在正常终止时要执行的函数。它提供了一种机制,使得开发者可以在程序结束时执行清理操作,例如释放资源、关闭文件、保存状态等
函数原型:
#include <stdlib.h>int atexit(void (*func)(void));
参数解析:
func 一个指向无参数、无返回值的函数的指针。这个函数将在程序正常终止时被调用。
返回值:
注册成功时返回0,注册失败(例如没有足够的空间来存储更多的退出函数)返回一个非0值。
代码示例:
#include <stdio.h>
#include <stdlib.h>void cleanup() {printf("Cleaning up resources...\n");
}int main() {if (atexit(cleanup) != 0) {fprintf(stderr, "Could not set exit function\n");return EXIT_FAILURE;}// 程序的其他部分printf("Program is terminating normally.\n");return EXIT_SUCCESS; // 或者直接 return 0;
}
注意事项:
注册的函数按照它们被注册的相反顺序调用。也就是说,最后注册的函数最先被调用。
通过atexit注册的函数只有程序通过exit或return从main函数中返回,或者调用_exit之外的终止函数时才会被调用。
同一个函数可以被多次注册,每次注册都会被调用。
1.5 程序终止相关宏
1.5.1 EXIT_SUCCESS 与 EXIT_FAILURE
EXIT_SUCCESS
宏定义,通常为0,用于表示程序终止。
#include <stdlib.h>int main() {// 程序成功执行return EXIT_SUCCESS;
}
EXIT_FAILURE
宏定义,通常值为非0值用于表示程序失败终止。
#include <stdlib.h>int main() {// 程序执行失败return EXIT_FAILURE;
}
相关文章:
Linux系统:进程终止的概念与相关接口函数(_exit,exit,atexit)
本节目标 理解进程终止的概念理解退出状态码的概念以及使用方法掌握_exit与exit函数的用法以及区别atexit函数注册终止时执行的函数相关宏 一、进程终止 进程终止(Process Termination)是指操作系统结束一个进程的执行,回收其占用的资源&a…...
Linux下 文件的查找、复制、移动和解压缩
1、在/var/log目录下创建一个hehe.log的文件,其文件内容是: myhostname ghl mydomain localdomain relayhost [smtp.qq.com]:587 smtp_use_tls yes smtp_sasl_auth_enable yes smtp_sasl_security_options noanonymous smtp_sasl_tls_security_opt…...
C语言学习之预处理指令
目录 预定义符号 #define的应用 #define定义常量 #define定义宏 带有副作用的宏参数 宏替换的规则 函数和宏定义的区别 #和## #运算符 ##运算符 命名约定 #undef 编辑 命令行定义 条件编译 头文件包含 头文件被包含的方式 1.本地头文件包含 2.库文件包含 …...
【STM32单片机】#10 USART串口通信
主要参考学习资料: B站江协科技 STM32入门教程-2023版 细致讲解 中文字幕 开发资料下载链接:https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwddspb 单片机套装:STM32F103C8T6开发板单片机C6T6核心板 实验板最小系统板套件科协 实验&…...
fastlio用mid360录制的bag包离线建图,提示消息类型错误
我用mid360录制的bag包,激光雷达的数据类型是sensor_msgs::PointCloud2,但是运行fast_lio中的mid360 launch文件,会报错(没截图),显示无法从livox_ros_driver2::CustomMsg转换到sensor_msgs::PointCloud2。…...
二级评论列表-Java实现
二级评论列表是很常见的功能,文章记录了新手用Java实现的具体逻辑。 整体实现逻辑是先用2个sql,分别查出两层数据。然后用java在service中实现数据组装,返给前端。这种实现思路好处是SQL简洁,逻辑分明,便于维护。 一…...
IP检测工具“ipjiance”
目录 IP质量检测 应用场景 对网络安全的贡献 对网络管理的帮助 对用户决策的辅助作用 IP质量检测 检测IP的网络提供商:通过ASN(自治系统编号)识别IP地址所属的网络运营商,例如电信、移动、联通等。 识别网络类型࿱…...
mysql的函数(第二期)
九、窗口函数(MySQL 8.0) 适用于对结果集的子集(窗口)进行计算,常用于数据分析场景。 ROW_NUMBER() 作用:为每一行生成唯一的序号。示例:按分数降序排名 SELECT n…...
Replicate Python client
本文翻译整理自:https://github.com/replicate/replicate-python 文章目录 一、关于 Replicate Python 客户端相关链接资源关键功能特性 二、1.0.0 版本的重大变更三、安装与配置1、系统要求2、安装3、认证配置 四、核心功能1、运行模型2、异步IO支持3、流式输出模型…...
halcon模板匹配(八)alignment_for_ocr_in_semiconductor
目录 一、alignment_for_ocr_in_semiconductor例程目的二、创建训练和查找用于图像对齐三、图像对齐四、在指定区域内查找文本一、alignment_for_ocr_in_semiconductor例程目的 在一个图像中定义两个区域,一个用于图像对齐,在另一个区域内使用文本模板进行匹配。 二、创建训…...
Java读取JSON文件并将其中元素转为JSON对象输出
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Java读取JSON文件并将其中元素转为JSON对象输…...
华为openEuler操作系统全解析:起源、特性与生态对比
华为openEuler操作系统全解析:起源、特性与生态对比 一、起源与发展历程 openEuler(欧拉操作系统)是华为于2019年开源的Linux发行版,其前身为华为内部研发的服务器操作系统EulerOS。EulerOS自2010年起逐步发展,支持华…...
Elasticsearch使用及常见的问题
Elasticsearch作为一款分布式搜索与分析引擎,其核心优势在于高性能搜索能力,依托倒排索引和分布式架构,可快速处理海量数据及复杂查询,支持实时索引与动态扩容,兼具高可用性和扩展性。其丰富的RESTful API与查询语言降…...
Python基础总结(七)之条件语句
文章目录 条件语句if一、Python中的真假二、条件语句格式2.1 if语句格式2.2 if-else语句2.3 if-elif-else语句 三、if语句嵌套 条件语句if 条件语句其实就是if语句,在讲解if语句之前需要知道Python中对于真假的判断。 一、Python中的真假 在Python中非0的都为真&…...
命令update-alternatives
❯ which pip /home/ying/anaconda3/bin/pipying192 ~ [2]> which pip /usr/bin/pip使用update-alternatives对他们进行管理和切换 快捷方式 和 实际路径不可以相同 所以我这边选择了/usr/local/bin目录作为介质存储快捷方式,另外该快捷方式会自己创建我们只需选…...
deekseak 本地windows 10 部署步骤
有些场景需要本地部署,例如金融、医疗(HIPAA)、政府(GDPR)、军工等,需完全控制数据存储和访问权限,避免云端合规风险或者偏远地区、船舶、矿井等无法依赖云服务,关键设施(…...
MySQL中常用函数的分类及示例
概述 以下是 MySQL 中常用函数的分类及示例,涵盖字符串处理、数值计算、日期操作、条件判断等常见场景: 一、字符串函数 1. CONCAT(str1, str2, ...) 拼接字符串。 SELECT CONCAT(Hello, , World); -- 输出: Hello World2. SUBSTRING(str, start,…...
<sql>、<resultMap>、<where>、<foreach>、<trim>、<set>等标签的作用和用法
目录 一. sql 代码片段标签 二. resultMap 映射结果集标签 三. where 条件标签 四. set 修改标签 五. trim 标签 六. foreach 循环标签 一. sql 代码片段标签 sql 标签是 mybatis 框架中一个非常常用的标签页,特别是当一张表很有多个字段多,或者要…...
企业级HAProxy高可用离线部署实战(附Kubernetes APIServer负载均衡配置)
企业级HAProxy高可用离线部署实战(附Kubernetes APIServer负载均衡配置) 摘要:本文深入讲解在离线环境下部署HAProxy 3.1.1的全流程,涵盖源码编译、系统服务封装、K8S APIServer四层负载配置等核心环节,并提供生产级高…...
实现Azure Databricks安全地请求企业内部API返回数据
需要编写一个Databricks在Azure云上运行,它需要访问企业内部的API获取JSON格式的数据,企业有网关和防火墙,API有公司的okta身份认证,通过公司的域账号来授权访问,现在需要创建一个专用的域账号,让Databrick…...
kafka认证部署
首先启动 zookeeper /home/kafka/bin/zookeeper-server-start.sh /home/kafka/config/zookeeper.properties 创建SCRAM证书 /home/kafka/bin/kafka-configs.sh --zookeeper localhost:2181 --alter --add-config SCRAM-SHA-256[iterations8192,passwordliebe],SCRAM-SHA-512[p…...
【项目】CherrySudio配置MCP服务器
CherrySudio配置MCP服务器 (一)Cherry Studio介绍(二)MCP服务环境搭建(1)环境准备(2)依赖组件安装<1> Bun和UV安装 (3)MCP服务器使用<1> 搜索MCP…...
【LeetCode 热题 100】双指针 系列
📁283. 移动零 对于该题目,需要注意的是两个地方,一是保持非零元素的相对顺序,以及O(1)的空间复杂度。 采用双指针的思路,将数组划分成3个区间,。 [0 , left]:该区间内元素全是非零元素。 [left1 , right…...
【技术派后端篇】 Redis 实现用户活跃度排行榜
在各类互联网应用中,排行榜是一个常见的功能需求,它能够直观地展示用户的表现或贡献情况,提升用户的参与感和竞争意识。在技术派项目中,也引入了用户活跃度排行榜,该排行榜主要基于 Redis 的 ZSET 数据结构来实现。接下…...
模拟算法(一)作业分析及答案
目录 作业1:角谷猜想 解题思路 : 代码实现: 作业2:校门外的树 解题思路 注意事项 代码实现 作业3:乒乓球 编辑 问题重述 解题思路: 作业1:角谷猜想 【描述】 所谓角谷猜想…...
西红柿番茄检测数据集VOC+YOLO格式2320张1类别可用于计数
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):2320 标注数量(xml文件个数):2320 标注数量(txt文件个数):2320 …...
企业级实战:将Java服务打包为Docker镜像的两种高效方法
企业级实战:将Java服务打包为Docker镜像的两种高效方法 摘要:本文针对Java服务容器化部署场景,提供 基于容器Commit 和 Dockerfile构建 两种镜像制作方案。重点解决动态库依赖、信号量配置、环境变量注入等企业级痛点问题,并提供…...
专题十六:虚拟路由冗余协议——VRRP
一、VRRP简介 VRRP(Virtual Router Redundancy Protocol)虚拟路由冗余协议通过把几台设备联合组成一台虚拟的设备,使用一定的机制保证当主机的下一跳设备出现故障时,及时将业务切换到备份设备,从而保持通讯的连续性和…...
Java中常见的锁synchronized、ReentrantLock、ReentrantReadWriteLock、StampedLock
在Java中,锁是实现多线程同步的核心机制。不同的锁适用于不同的场景,理解其实现原理和使用方法对优化性能和避免并发问题至关重要。 一、隐式锁:synchronized 关键字 实现原理 基于对象监视器(Monitor):每…...
DDPM(diffusion)原理
DDPM(diffusion)原理 1、DDPM(原理)2、DDPM和 Conditional DDPM(原理解释)2.1. Diffusion Models 原理详解核心思想前向扩散过程(Forward Diffusion)反向去噪过程(Revers…...
