当前位置: 首页 > news >正文

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;
}

相关文章:

  • BT1120 BT656驱动相关代码示例
  • 计算机网络八股——HTTP协议与HTTPS协议
  • Linux疑难杂惑 | 云服务器重装系统后vscode无法远程连接的问题
  • 针对MCP认证考试中的常见技术难题进行实战分析与解决方案分享
  • Windows桌面图标变白的解决方案
  • springboot--web开发请求参数接收注解
  • GD32H7单片机使用segger_rtt,rtt-viewer看不到输出的问题,怎样解决?
  • 07-DevOps-安装部署Harbor镜像仓库
  • 小刚说C语言刷题——1035 判断成绩等级
  • 资源-又在网上淘到金了
  • csdn教程
  • 黑马点评秒杀优化
  • 手撕 简易HashMap
  • 2025.04.19-阿里淘天春招算法岗笔试-第二题
  • 【基础】回文数个数
  • Java—— 常见API介绍 第二期
  • 【数据结构_11】二叉树(3)
  • 并发网路通信-套接字通信
  • phpy通用扩展:让PHP和Python手拉手
  • 最新得物小程序sign签名加密,请求参数解密,响应数据解密逆向分析
  • 文甦任四川乐山市委副书记,曾赴外交部挂职副司长
  • 人民日报:各地扎实开展学习教育,一体推进学查改
  • 对话|棋后居文君:创造历史之后,还有继续追梦的心
  • 85岁眼科专家、武汉大学人民医院原眼科主任喻长泰逝世
  • 特朗普就防卫负担施压日本,石破茂:防卫费应由我们自主决定
  • 市场监管总局:在全国集中开展食用植物油突出问题排查整治