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

Linux 系统错误处理简介

Linux 系统错误处理简介

      • 1. `errno`:错误代码的载体
      • 2. `strerror()`:错误信息的翻译官
      • 3. `perror()`:便捷的错误信息输出
      • 4. 系统调用与库函数的区别
      • 5. 错误处理的最佳实践

在 C/C++ 程序开发中,我们经常需要处理各种错误情况
Linux 系统提供了一套完善的错误处理机制,通过全局变量 errno 和相关的库函数,我们可以方便地定位和处理错误

1. errno:错误代码的载体

errno 是一个整型的全局变量,定义在 <errno.h> 头文件中。当一个函数调用发生错误时,通常会将相应的错误代码存储在 errno 中。通过检查 errno 的值,我们可以判断函数调用是否成功以及失败的原因。

需要注意的是:

  • 并非所有库函数在调用失败时都会设置 errno 的值。只有属于系统调用的函数才会设置 errno。可以通过 man 手册来确认某个函数是否会设置 errno
  • errno 不能作为判断库函数调用是否失败的唯一标志。正确的做法是先检查函数的返回值,只有当返回值表明函数调用失败时,才需要关注 errno 的值。
  • errno 的值只有在库函数调用发生错误时才会被设置,当库函数调用成功时,errno 的值不会被修改,也不会主动置为 0。

2. strerror():错误信息的翻译官

strerror() 函数定义在 <string.h> 头文件中,用于将错误代码转换为相应的错误信息字符串。

char *strerror(int errnum);            // 非线程安全
int strerror_r(int errnum, char *buf, size_t buflen);    // 线程安全

其中,errnum 是错误代码,strerror() 返回一个指向错误信息字符串的指针。strerror_r()strerror() 的线程安全版本,它将错误信息存储在用户提供的缓冲区 buf 中。

3. perror():便捷的错误信息输出

perror() 函数定义在 <stdio.h> 头文件中,用于在控制台输出最近一次系统错误的详细信息。

void perror(const char *s);

perror() 接受一个字符串 s 作为参数,它会将 s 和最近一次系统错误的描述信息一起输出到标准错误流(stderr)。在实际开发中,由于服务程序通常在后台运行,通过控制台显示错误信息意义不大。perror() 主要用于调试程序。

4. 系统调用与库函数的区别

在讨论 errno 的适用范围时,我们提到了“系统调用”的概念。理解系统调用与库函数的区别对于理解 Linux 系统错误处理至关重要。

系统调用是操作系统内核提供给用户程序的一组接口,用于访问操作系统提供的各种服务,例如文件 I/O、进程管理、内存管理等。系统调用直接与内核交互,运行在内核态。

库函数是程序员为了方便开发而封装的一系列函数,它们通常是对系统调用的封装或组合,也可能不涉及系统调用。库函数运行在用户态。

以下是系统调用与库函数的一些主要区别:

特性系统调用库函数
定义操作系统内核提供的接口程序员封装的函数
运行空间内核态用户态
可移植性不同操作系统之间通常不同遵循标准(如 ANSI C)则可移植性较好
性能开销较大(需要用户态和内核态切换)开销较小
功能提供最基本、最底层的操作系统服务提供更高级、更方便的功能
errno通常会设置 errno并非都会设置 errno

举例来说,open()read()write() 等是系统调用,而 fopen()fread()fwrite() 等是库函数。fopen() 等库函数底层会调用相应的系统调用来完成文件操作。

5. 错误处理的最佳实践

在实际开发中,我们应该遵循以下几点:

  • 始终检查函数的返回值,判断函数调用是否成功。
  • 只有当返回值表明函数调用失败时,才需要关注 errno 的值。
  • 使用 strerror()perror() 获取详细的错误信息,方便定位问题。
  • 根据不同的错误类型采取相应的处理措施,例如重试、记录日志、退出程序等。
  • 在多线程环境下,应使用 strerror_r() 等线程安全的函数。
http://www.lryc.cn/news/525020.html

相关文章:

  • 逐笔成交逐笔委托Level2高频数据下载和分析:20250122
  • 第18个项目:微信开发入门:获取access_token的Python源码
  • 如何将自己本地项目开源到github上?
  • Windows远程连接Docker服务
  • 在Qt中实现点击一个界面上的按钮弹窗到另一个界面
  • 嵌入式知识点总结 ARM体系与架构 专题提升(一)-硬件基础
  • 全氟醚橡胶发展前景:高性能密封材料的璀璨之星
  • Android程序中使用FFmpeg库
  • Spring 依赖注入详解:创建 Bean 和注入依赖是一回事吗?
  • 【动态规划】落花人独立,微雨燕双飞 - 8. 01背包问题
  • 浅说树上差分——点差分
  • All in大模型!智能座舱语音交互决胜2025
  • windows git bash 使用zsh 并集成 oh my zsh
  • Git进阶笔记系列(01)Git核心架构原理 | 常用命令实战集合
  • IDEA导入Maven工程不识别pom.xml
  • AT8870单通道直流电机驱动芯片
  • 计算机视觉算法实战——实体物体跟踪
  • 网络协议如何确保数据的安全传输?
  • 在elasticsearch中,document数据的写入流程如何?
  • 【优选算法】6----查找总价格为目标值的两个商品
  • 99.8 金融难点通俗解释:净资产收益率(ROE)
  • Java设计模式—观察者模式
  • 人工智能在数字化转型中的角色:从数据分析到智能决策
  • 论文阅读 Multi-view Classification Using Hybrid Fusion and Mutual Distillation
  • AIGC浪潮下,图文内容社区数据指标体系如何构建?
  • ”彩色的验证码,使用pytesseract识别出来的验证码内容一直是空“的解决办法
  • 前端Vue2项目使用md编辑器
  • OpenVela 架构剖析:从内核到应用
  • vue视频流播放,支持多种视频格式,如rmvb、mkv
  • 记一个Timestamp时区问题的坑