Linux系统:进程终止的概念与相关接口函数(_exit,exit,atexit)

本节目标

  • 理解进程终止的概念
  • 理解退出状态码的概念以及使用方法
  • 掌握_exit与exit函数的用法以及区别
  • atexit函数注册终止时执行的函数
  • 相关宏

一、进程终止

进程终止(Process Termination)是指操作系统结束一个进程的执行,回收其占用的资源(如内存、文件描述符等)的过程。它是操作系统管理进程生命周期的重要环节,确保系统资源的有效利用和稳定性。

1.1 进程退出的场景

正常终止

  • 程序执行完成:进程完成了其预定的任务,如计算完成、文件处理完毕等。
  • 显式调用终止函数:程序通过调用系统提供的终止函数(如 exit()_Exit() 或 return)主动请求终止。

异常终止

  • 运行错误:如除以零、访问非法内存地址等。
  • 信号触发:操作系统或用户通过发送信号(如 SIGKILLSIGTERM)强制终止进程。
  • 资源耗尽:如内存不足、文件描述符耗尽等。

外部干预

  • 用户手动终止:通过任务管理器或命令行工具(如 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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/110.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[苍穹外卖 | 项目日记] 第三天

前言 实现了新增菜品接口实现了菜品分页查询接口实现了删除菜品接口实现了根据id查询菜品接口实现了修改菜品接口 今日收获&#xff1a; 今日的这几个接口其实和之前写的对员工的操作是一样的&#xff0c;都是一整套Curd操作&#xff0c;所以今天在技术层面上并没有…

用 NLP + Streamlit,把问卷变成能说话的反馈

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…

算法01-最小生成树prim算法

最小生成树prim算法 题源&#xff1a;代码随想录卡哥的题 链接&#xff1a;https://kamacoder.com/problempage.php?pid1053 时间&#xff1a;2025-04-18 难度&#xff1a;4⭐ 题目&#xff1a; 1. 题目描述&#xff1a; 在世界的某个区域&#xff0c;有一些分散的神秘岛屿&…

利用deepseek+Mermaid画流程图

你是一个产品经理&#xff0c;请绘制一个流程图&#xff0c;要求生成符合Mermaid语法的代码&#xff0c;要求如下&#xff1a; 用户下载文件、上传文件、删除文件的流程过程符合安全规范细节具体到每一步要做什么 graph LRclassDef startend fill:#F5EBFF,stroke:#BE8FED,str…

stl 容器 – map

stl 容器 – map 1. map 和 multimap的使用文档 参考文档 参考文档点这里哟 &#x1f308; &#x1f618; 2. map 类的介绍 map的声明如下 template < class Key, // map::key_type class T, // map::mapped_type class Compare less<Key>, // map::key_…

计算机视觉cv2入门之车牌号码识别

前边我们已经讲解了使用cv2进行图像预处理与边缘检测等方面的知识&#xff0c;这里我们以车牌号码识别这一案例来实操一下。 大致思路 车牌号码识别的大致流程可以分为这三步&#xff1a;图像预处理-寻找车牌轮廓-车牌OCR识别 接下来我们按照这三步来进行讲解。 图像预处理 …

Spring Boot 3 + SpringDoc:打造接口文档

1、背景公司 新项目使用SpringBoot3.0以上构建&#xff0c;其中需要对外输出接口文档。接口文档一方面给到前端调试&#xff0c;另一方面给到测试使用。 2、SpringDoc 是什么&#xff1f; SpringDoc 是一个基于 Spring Boot 项目的库&#xff0c;能够自动根据项目中的配置、…

多路由器通过三层交换机互相通讯(单臂路由+静态路由+默认路由版),通过三层交换机让pc端相互通讯

多路由器通过三层交换机互相通讯&#xff08;单臂路由静态路由默认路由版&#xff09; 先实现各个小框框里能够互通 哇咔 交换机1&#xff08;二层交换机,可看配置单臂路由的文章) Switch>en Switch#conf t Switch(config)#int f0/1 Switch(config-if)#switchport access…

通过gird布局实现div的响应式分布排列

目标&#xff1a;实现对于固定宽度的div盒子在页面中自适应排布&#xff0c;并且最后一行的div盒子可以与前面的盒子对齐。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" con…

AI Agent系列(九) -Data Agent(数据分析智能体)

AI Agent系列【九】 前言一、Data Agent场景二、Data Agent核心因素2.1 数据源2.2 大模型2.3 应用及可视化 三、Data Agent应用场景 前言 Data Agent就是在大模型基础上构建一个数据分析的智能体&#xff0c;是一种基于人工智能技术&#xff0c;特别是大模型技术的数据分析智…

AUTOSAR图解==>AUTOSAR_SWS_DefaultErrorTracer

AUTOSAR 默认错误追踪器(Default Error Tracer)详细分析 基于AUTOSAR 4.4.0规范的深入解析 目录 概述 DET模块的作用DET模块的定位 架构设计 模块架构接口设计 状态与行为 状态转换错误报告流程 API与数据结构 API概览数据类型定义 配置与扩展 模块配置回调机制 总结 1. 概述 …

Linux,redis群集模式,主从复制,读写分离

redis的群集模式 主从模式 &#xff08;单项复制&#xff0c;主复制到从&#xff09; 一主两从 一台主机上的一主两从 需要修改三个配置文件 主要端口不一样 redis-8001.conf redis-8002.conf redis-8003.conf 哨兵模式 分布式集群模式 redis 安装部署 1&#xff0c;下载…