写给初学者的Linux errno 错误码机制

不同于Java的异常处理机制, 当你使用C更多的接触到是基于错误码的异常机制, 简单来说就是当调用的函数发生异常时, 程序不会跳转到一个统一处理异常的地方, 取而代之的是返回一个整型错误码。

可能会有小伙伴有疑问了, 以打开文件为例该函数定义如下所示

int open(const char *pathname, int flags);

如果打开文件成功, open函数会返回一个文件描述符(该值大于0), 如果失败则返回 -1。对于开发者来说, 只知道文件打开失败了, 而却不知道具体原因, 实际上的原因可能是多种多样的, 如:

  • 文件不存在
  • 当前进程对文件没有读写权限
    [En]

    the current process does not have read and write access to the file*

那么该如何知道具体错误呢? 这就需要借助系统为我们提供的 errno机制了。

errno

errno是一个定义在 errno.h头文件的全局整型变量,表示当前发生的最后一个错误, 只需在代码中引用 errno.h这个头文件边可以获取到这个值。

如以下demo所示, 我们尝试打开一个不存在的文件

#include
#include
#include
#include

int main() {
    int fd;
    fd = open("/test.log", O_RDONLY);
    if (fd == -1) {
        printf("open failed, errno: %d\n", errno);
    }
    return 0;
}

运行该程序, 输出如下所示:

open failed, errno: 2

可以看出,此时错误码为 2, 怎么知道这个错误码代表什么意思呢?

有以下方式

moreutils

  1. 安装moreutils
apt install moreutils
  1. 运行 errno 错误码查看具体的错误信息
    写给初学者的Linux errno 错误码机制

可以验证, 错误码2表示当前文件或目录不存在,与我们的预期一致

perror

使用定义在 stdio.h中的 perror函数可以直接在标准输出上打印错误信息

该函数定义如下所示, 我们可以在错误信息前附加自己定义的错误信息。

void perror(const char *s);

Demo:

int main() {
    int fd;
    fd = open("/test.log", O_RDONLY);
    if (fd == -1) {
        perror("open failed");
    }
    return 0;
}

输出:

写给初学者的Linux errno 错误码机制

strerr

如果我们只需要获取错误码对应的文本以记录日志, 可以使用 strerr函数, 该函数定义在 string.h

Demo:

int main() {
    int fd;
    fd = open("/test.log", O_RDONLY);
    if (fd == -1) {
      char* err_msg = strerror(errno);
      printf("%s\n", err_msg);
    }
    return 0;
}

输出

写给初学者的Linux errno 错误码机制

线程安全的吗?

相信对于并发问题比较敏感的同学已经意识到了一个问题:这 errno是一个整型的全局变量, 那如果多个线程同时执行系统调用, 并且都因为不同的原因失败了, 会不会导致其他线程的错误信息全部被最后一个产生错误的线程给覆盖掉了? 以及会不会有线程安全问题呢?

实际上 errno被定义为了线程局部变量, 概念同Java中的 ThreadLocal, 即每个线程都会有自己的errno变量, 不同线程之间不会互相影响。

Original: https://www.cnblogs.com/kovogo/p/15535780.html
Author: kovogo
Title: 写给初学者的Linux errno 错误码机制

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/524383/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 命名空间、作用域、LEGB法则、垃圾回收机制

    一、命名空间、作用域、LEGB法则、 1.命名空间和作用域 :   命名&#x7A7…

    Linux 2023年6月8日
    083
  • Linux之Nginx模块扩展

    404. 抱歉,您访问的资源不存在。 可能是URL不正确,或者对应的内容已经被删除,或者处于隐私状态。 [En] It may be that the URL is incorre…

    Linux 2023年5月27日
    072
  • 测试计划

    ​ 1.测试计划的定义:描述需要完成的所有工作,包括被测项目的目的、背景、范围、资源、进度、环境、任务、策略,以及相应的风险和措施。 ​ 2.测试计划的作用: 对后面的测试过程起到…

    Linux 2023年6月7日
    072
  • 那些shellcode免杀总结

    首发先知: https://xz.aliyun.com/t/7170 自己还是想把一些shellcode免杀的技巧通过白话文、傻瓜式的文章把技巧讲清楚。希望更多和我一样web狗也能…

    Linux 2023年5月28日
    077
  • PHP实现无限级分类

    $array = array( array(‘id’ => 1, ‘pid’ => 0, ‘name’ => ‘河北省’), array(‘id’ => 2…

    Linux 2023年6月7日
    065
  • 原来这就是网络

    你是一台电脑,你的名字叫A,很久很久之前,你不与任何其他电脑相连接,孤苦伶仃。 直到有一天,你希望与另一台电脑B建立连接,于是你们各开了一个网口,用一根网线连接了起来。 用一根网线…

    Linux 2023年6月14日
    0103
  • JavaScript快速入门-07-异常处理与调试

    7、异常处理与调试 7.1 异常处理 7.1.1 try/catch语句 try/catch语句常用于处理JavaScript中的异常,其基本语法如下所示: try { // 可能…

    Linux 2023年6月7日
    0100
  • 驳”一切不谈考核的管理都是扯淡”

    一、引子 以我个人的从业经验认为,研发人员的量化考核,始终是一个世界难题。正巧不久前在园子里看到了 “一切不谈考核的管理都是扯淡!”一文(下面简称为&#82…

    Linux 2023年6月13日
    086
  • prometheus operator 监控redis-exporter

    创建 redis-exporter service bash;gutter:false; apiVersion: v1 kind: Service metadata: labels…

    Linux 2023年5月28日
    091
  • Nginx基础入门篇(3)—返回状态码详解

    一般常见返回状态码 200 – 服务器成功返&a…

    Linux 2023年6月6日
    090
  • 灵敏度分析简介

    参考文章1 😄参考文章2 😸参考文章3 😃 1. 灵敏度分析: 某一个假定的常量,在现实中不可能完全保持不变,可能发生一定范围的波动。灵敏度分析就是检验这部分波动对结果的影响。 灵…

    Linux 2023年6月14日
    094
  • MapReduce入门实例——WordCount

    摘要:MapReduce的IDEA配置及WordCount案例 Maven项目配置 创建一个空的Maven项目 打开根目录下的 pom.xml文件,参考配置: UTF-8 3.2….

    Linux 2023年6月8日
    090
  • 设计模式——命令模式

    命令模式定义 将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和回复的功能。 Receive接收者角色 该角色就是干活…

    Linux 2023年6月7日
    0106
  • Ubuntu系统报错The system is running in low-graphics mode

    我遇到过两次这种请况,这次解决了。很nice! 在csdn上搜到的大部分操作是: 鼠标进入系统 使用快捷键 Ctrl+Alt+F1 进入用户 输入密码 然后按照以下代码进行 cd …

    Linux 2023年5月27日
    097
  • 学习一下 SpringCloud (一)– 从单体架构到微服务架构、代码拆分(maven 聚合)

    一、架构演变 1、系统架构、集群、分布式系统 简单理解 (1)什么是系统架构? 【什么是系统架构?】 系统架构 描述了 在应用程序内部,如何根据 业务、技术、灵活性、可扩展性、可维…

    Linux 2023年6月11日
    093
  • 运算符重载和深浅拷贝

    对于某些运算符号(+,-,,/….),我们不满足与它原有的操作方式,而是要在对 特有对象(如负数的加减)进行使用,但是编译器会不允许这样做,因为会与操作符 原本的类型不…

    Linux 2023年6月7日
    092
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球