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

news2025/4/20 7:13:48

本节目标

  • 理解进程终止的概念
  • 理解退出状态码的概念以及使用方法
  • 掌握_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.coloradmin.cn/o/2338559.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux下 文件的查找、复制、移动和解压缩

1、在/var/log目录下创建一个hehe.log的文件&#xff0c;其文件内容是&#xff1a; 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串口通信

主要参考学习资料&#xff1a; B站江协科技 STM32入门教程-2023版 细致讲解 中文字幕 开发资料下载链接&#xff1a;https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwddspb 单片机套装&#xff1a;STM32F103C8T6开发板单片机C6T6核心板 实验板最小系统板套件科协 实验&…

fastlio用mid360录制的bag包离线建图,提示消息类型错误

我用mid360录制的bag包&#xff0c;激光雷达的数据类型是sensor_msgs::PointCloud2&#xff0c;但是运行fast_lio中的mid360 launch文件&#xff0c;会报错&#xff08;没截图&#xff09;&#xff0c;显示无法从livox_ros_driver2::CustomMsg转换到sensor_msgs::PointCloud2。…

二级评论列表-Java实现

二级评论列表是很常见的功能&#xff0c;文章记录了新手用Java实现的具体逻辑。 整体实现逻辑是先用2个sql&#xff0c;分别查出两层数据。然后用java在service中实现数据组装&#xff0c;返给前端。这种实现思路好处是SQL简洁&#xff0c;逻辑分明&#xff0c;便于维护。 一…

IP检测工具“ipjiance”

目录 IP质量检测 应用场景 对网络安全的贡献 对网络管理的帮助 对用户决策的辅助作用 IP质量检测 检测IP的网络提供商&#xff1a;通过ASN&#xff08;自治系统编号&#xff09;识别IP地址所属的网络运营商&#xff0c;例如电信、移动、联通等。 识别网络类型&#xff1…

Replicate Python client

本文翻译整理自&#xff1a;https://github.com/replicate/replicate-python 文章目录 一、关于 Replicate Python 客户端相关链接资源关键功能特性 二、1.0.0 版本的重大变更三、安装与配置1、系统要求2、安装3、认证配置 四、核心功能1、运行模型2、异步IO支持3、流式输出模型…

deekseak 本地windows 10 部署步骤

有些场景需要本地部署&#xff0c;例如金融、医疗&#xff08;HIPAA&#xff09;、政府&#xff08;GDPR&#xff09;、军工等&#xff0c;需完全控制数据存储和访问权限&#xff0c;避免云端合规风险或者偏远地区、船舶、矿井等无法依赖云服务&#xff0c;关键设施&#xff08…

<sql>、<resultMap>、<where>、<foreach>、<trim>、<set>等标签的作用和用法

目录 一. sql 代码片段标签 二. resultMap 映射结果集标签 三. where 条件标签 四. set 修改标签 五. trim 标签 六. foreach 循环标签 一. sql 代码片段标签 sql 标签是 mybatis 框架中一个非常常用的标签页&#xff0c;特别是当一张表很有多个字段多&#xff0c;或者要…

【项目】CherrySudio配置MCP服务器

CherrySudio配置MCP服务器 &#xff08;一&#xff09;Cherry Studio介绍&#xff08;二&#xff09;MCP服务环境搭建&#xff08;1&#xff09;环境准备&#xff08;2&#xff09;依赖组件安装<1> Bun和UV安装 &#xff08;3&#xff09;MCP服务器使用<1> 搜索MCP…

【技术派后端篇】 Redis 实现用户活跃度排行榜

在各类互联网应用中&#xff0c;排行榜是一个常见的功能需求&#xff0c;它能够直观地展示用户的表现或贡献情况&#xff0c;提升用户的参与感和竞争意识。在技术派项目中&#xff0c;也引入了用户活跃度排行榜&#xff0c;该排行榜主要基于 Redis 的 ZSET 数据结构来实现。接下…

模拟算法(一)作业分析及答案

目录 作业1&#xff1a;角谷猜想 解题思路 &#xff1a; 代码实现&#xff1a; 作业2&#xff1a;校门外的树 解题思路 注意事项 代码实现 作业3&#xff1a;乒乓球 ​编辑 问题重述 解题思路&#xff1a; 作业1&#xff1a;角谷猜想 【描述】 所谓角谷猜想&#xf…

西红柿番茄检测数据集VOC+YOLO格式2320张1类别可用于计数

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;2320 标注数量(xml文件个数)&#xff1a;2320 标注数量(txt文件个数)&#xff1a;2320 …

专题十六:虚拟路由冗余协议——VRRP

一、VRRP简介 VRRP&#xff08;Virtual Router Redundancy Protocol&#xff09;虚拟路由冗余协议通过把几台设备联合组成一台虚拟的设备&#xff0c;使用一定的机制保证当主机的下一跳设备出现故障时&#xff0c;及时将业务切换到备份设备&#xff0c;从而保持通讯的连续性和…

DDPM(diffusion)原理

DDPM&#xff08;diffusion&#xff09;原理 1、DDPM&#xff08;原理&#xff09;2、DDPM和 Conditional DDPM&#xff08;原理解释&#xff09;2.1. Diffusion Models 原理详解核心思想前向扩散过程&#xff08;Forward Diffusion&#xff09;反向去噪过程&#xff08;Revers…

《软件设计师》复习笔记(2.2)——效验码、体系结构、指令、流水线

目录 一、校验码 码距 奇偶校验码 循环冗余校验码&#xff08;CRC&#xff09; 海明码 真题示例&#xff1a; 二、体系结构 Flynn分类法 三、指令系统 指令组成 指令执行过程 指令的寻址方式 操作数的寻址方式 CISC vs RISC 真题示例&#xff1a; 四、流水线技…

IsaacSim Asserts 配置

IsaacSim Asserts 配置 背景解决方案资源准备具体操作步骤验证 背景 我是习惯使用 isaacsim 的 standalone 模式&#xff0c;使用 python 脚本直接运行 script&#xff0c;然后弹窗&#xff0c;按照规则正确运行即可&#xff0c;但是&#xff0c;这就导致了一些问题出现&#…

接口自动化 ——fixture allure

一.参数化实现数据驱动 上一篇介绍了参数化&#xff0c;这篇 说说用参数化实现数据驱动。在有很多测试用例的时候&#xff0c;可以将测试用例都存储在文件里&#xff0c;进行读写调用。本篇主要介绍 csv 文件和 json 文件。 1.读取 csv 文件数据 首先创建 csv 文件&#xff…

systemctl管理指令

今天我们来继续学习服务管理指令,接下来才是重头戏-systemctl,那么话不多说,直接开始吧. systemctl管理指令 1.基本语法: systemctl [start | stop | restart | status]服务 注&#xff1a;systemctl指令管理的服务在/usr/lib/ systemd/system查看 2.systemctl设置服务的自…

【文件操作与IO】详细解析文件操作与IO (二)

本篇博客是上一篇文章的续写,重点介绍数据流,还包括三道练习题. &#x1f40e;文章专栏: JavaEE初阶 &#x1f680;若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 . 王子,公主请阅&#x1f680; 要开心…