一、errno 介绍

1.1 errno 简介

Linux 中系统调用的错误都存储于错误码 errno 中。errno 由操作系统维护,存储就近发生的错误,即下一次的错误码会覆盖掉上一次的错误。

errno 是一个包含在 <errno.h> 中的预定义的外部 int 变量,用于表示最近一个函数调用是否产生了错误。

  • 若为0,则无错误;
  • 其它值均表示某一种错误。

代码中需要包含 #include <errno.h>,当一个系统调用或着库函数的调用失败时,将会重置错误码 errno。用户在判断程序出错后,立即检验 errno 的值可以获取错误码和错误信息。

1.2 errno是线程安全的

在 Linux 上,全局 errno 变量是特定于线程的。POSIX 要求 errno 必须是线程安全的。

参阅:Thread-safety and POSIX.1 (unix.org)

在 POSIX.1 中,errno 被定义为外部全局变量。但是此定义在多线程环境中是不可接受的,因为使用它会导致不确定的结果。问题是两个或多个线程可能会遇到错误,所有错误都会导致设置相同的错误号。在这种情况下,一个线程可能已经被另一个线程更新后,最终检查 errno。

为了避免产生不确定性,POSIX.1c 将 errno 重新定义为可以访问每个线程错误号的服务:

  • 某些函数可能在通过符号 errno 访问的变量中提供错误号。
  • errno 符号是通过包括 C 标准所指定的标头来定义的。
  • 对于进程的每个线程,errno 的值不应受函数调用或其他线程对 errno 的分配的影响。

参阅:errno(3): number of last error - Linux man page (die.net)

errno 是线程本地的;在一个线程中设置它不会影响在其他任何线程中的值

我们可以通过在机器上运行一个简单的程序来进行检查。

#include <stdio.h>
#include <pthread.h>
#include <errno.h> #define NTHREADS 5 void *thread_function(void *dummyPtr)
{
printf("Thread number %ld addr(errno):%p\n", pthread_self(), &errno);
} int main()
{
pthread_t thread_id[NTHREADS];
int i, j; for (i = 0; i < NTHREADS; i++)
{
pthread_create(&thread_id[i], NULL, thread_function, NULL);
} for (j = 0; j < NTHREADS; j++)
{
pthread_join(thread_id[j], NULL);
} return 0;
}

输出结果:

1.3 errno 宏定义

在头文件「/usr/include/asm-generic/errno-base.h」中对基础的常用 errno 进行了宏定义:

define errno explain
EPERM 1 Operation not permitted
ENOENT 2 No such file or directory
ESRCH 3 No such process
EINTR 4 Interrupted system call
EIO 5 I/O error
ENXIO 6 No such device or address
E2BIG 7 Argument list too long
ENOEXEC 8 Exec format error
EBADF 9 Bad file number
ECHILD 10 No child processes
EAGAIN 11 Try again
ENOMEM 12 Out of memory
EACCES 13 Permission denied
EFAULT 14 Bad address
ENOTBLK 15 Block device required
EBUSY 16 Device or resource busy
EEXIST 17 File exists
EXDEV 18 Cross-device link
ENODEV 19 No such device
ENOTDIR 20 Not a directory
EISDIR 21 Is a directory
EINVAL 22 Invalid argument
ENFILE 23 File table overflow
EMFILE 24 Too many open files
ENOTTY 25 Not a typewriter
ETXTBSY 26 Text file busy
EFBIG 27 File too large
ENOSPC 28 No space left on device
ESPIPE 29 Illegal seek
EROFS 30 Read-only file system
EMLINK 31 Too many links
EPIPE 32 Broken pipe
EDOM 33 Math argument out of domain of func
ERANGE 34 Math result not representable

在 「/usr/include/asm-generic/errno.h」 中,对剩余的 errno 做了宏定义:

define errno explain
EDEADLK 35 Resource deadlock would occur
ENAMETOOLONG 36 File name too long
ENOLCK 37 No record locks available
ENOSYS 38 Function not implemented
ENOTEMPTY 39 Directory not empty
ELOOP 40 Too many symbolic links encountered
EWOULDBLOCK EAGAIN Operation would block
ENOMSG 42 No message of desired type
EIDRM 43 Identifier removed
ECHRNG 44 Channel number out of range
EL2NSYNC 45 Level 2 not synchronized
EL3HLT 46 Level 3 halted
EL3RST 47 Level 3 reset
ELNRNG 48 Link number out of range
EUNATCH 49 Protocol driver not attached
ENOCSI 50 No CSI structure available
EL2HLT 51 Level 2 halted
EBADE 52 Invalid exchange
EBADR 53 Invalid request descriptor
EXFULL 54 Exchange full
ENOANO 55 No anode
EBADRQC 56 Invalid request code
EBADSLT 57 Invalid slot
EDEADLOCK EDEADLK
EBFONT 59 Bad font file format
ENOSTR 60 Device not a stream
ENODATA 61 No data available
ETIME 62 Timer expired
ENOSR 63 Out of streams resources
ENONET 64 Machine is not on the network
ENOPKG 65 Package not installed
EREMOTE 66 Object is remote
ENOLINK 67 Link has been severed
EADV 68 Advertise error
ESRMNT 69 Srmount error
ECOMM 70 Communication error on send
EPROTO 71 Protocol error
EMULTIHOP 72 Multihop attempted
EDOTDOT 73 RFS specific error
EBADMSG 74 Not a data message
EOVERFLOW 75 Value too large for defined data type
ENOTUNIQ 76 Name not unique on network
EBADFD 77 File descriptor in bad state
EREMCHG 78 Remote address changed
ELIBACC 79 Can not access a needed shared library
ELIBBAD 80 Accessing a corrupted shared library
ELIBSCN 81 .lib section in a.out corrupted
ELIBMAX 82 Attempting to link in too many shared libraries
ELIBEXEC 83 Cannot exec a shared library directly
EILSEQ 84 Illegal byte sequence
ERESTART 85 Interrupted system call should be restarted
ESTRPIPE 86 Streams pipe error
EUSERS 87 Too many users
ENOTSOCK 88 Socket operation on non-socket
EDESTADDRREQ 89 Destination address required
EMSGSIZE 90 Message too long
EPROTOTYPE 91 Protocol wrong type for socket
ENOPROTOOPT 92 Protocol not available
EPROTONOSUPPORT 93 Protocol not supported
ESOCKTNOSUPPORT 94 Socket type not supported
EOPNOTSUPP 95 Operation not supported on transport endpoint
EPFNOSUPPORT 96 Protocol family not supported
EAFNOSUPPORT 97 Address family not supported by protocol
EADDRINUSE 98 Address already in use
EADDRNOTAVAIL 99 Cannot assign requested address
ENETDOWN 100 Network is down
ENETUNREACH 101 Network is unreachable
ENETRESET 102 Network dropped connection because of reset
ECONNABORTED 103 Software caused connection abort
ECONNRESET 104 Connection reset by peer
ENOBUFS 105 No buffer space available
EISCONN 106 Transport endpoint is already connected
ENOTCONN 107 Transport endpoint is not connected
ESHUTDOWN 108 Cannot send after transport endpoint shutdown
ETOOMANYREFS 109 Too many references: cannot splice
ETIMEDOUT 110 Connection timed out
ECONNREFUSED 111 Connection refused
EHOSTDOWN 112 Host is down
EHOSTUNREACH 113 No route to host
EALREADY 114 Operation already in progress
EINPROGRESS 115 Operation now in progress
ESTALE 116 Stale file handle
EUCLEAN 117 Structure needs cleaning
ENOTNAM 118 Not a XENIX named type file
ENAVAIL 119 No XENIX semaphores available
EISNAM 120 Is a named type file
EREMOTEIO 121 Remote I/O error
EDQUOT 122 Quota exceeded
ENOMEDIUM 123 No medium found
EMEDIUMTYPE 124 Wrong medium type
ECANCELED 125 Operation Canceled
ENOKEY 126 Required key not available
EKEYEXPIRED 127 Key has expired
EKEYREVOKED 128 Key has been revoked
EKEYREJECTED 129 Key was rejected by service
EOWNERDEAD 130 Owner died
ENOTRECOVERABLE 131 State not recoverable
ERFKILL 132 Operation not possible due to RF-kill
EHWPOISON 133 Memory page has hardware error

二、打印 errno

若想要打印 errno,需要包含头文件 #include <errno.h>

2.1 使用 perror 打印错误信息

函数原型:void perror(const char *s)

头 文 件:#include <stdio.h>

作 用:打印系统错误信息

2.2 使用 strerror 显示错误信息

函数原型:char *strerror(int errnum);

头 文 件:#include <string.h>

作 用:将错误码以字符串的信息显示出来

三、输出 errno 的小 Demo

#include <stdio.h>
#include <string.h> static void __Process(char *str)
{
if (strstr(str, "_ASM_GENERIC_") != NULL || strstr(str, "define") == NULL)
{
return;
}
if (strstr(str, "EWOULDBLOCK") != NULL || strstr(str, "EDEADLOCK") != NULL)
{
return;
} char szDefine[64] = {0};
int errno = -1;
char szExplain[64] = {0};
sscanf(str, "%*[^A-Z]%s%*[^0-9]%d %*[^*]* %[^*]s", szDefine, &errno, szExplain);
szExplain[strlen(szExplain) - 1] = 0; // 去除最后的空格 char buf[1024] = {0};
snprintf(buf, sizeof(buf), "|%s|%d|%s|", szDefine, errno, szExplain);
puts(buf);
} int main()
{
freopen("/usr/include/asm-generic/errno-base.h", "r", stdin); // 读文件
// freopen("E:\\Documents\\stdin&&stdout\\stdout\\文件名", "w", stdout); // 写文件 while (1)
{
char str[1024] = {0};
fgets(str, sizeof(str), stdin); if (0 == strncmp(str, "#endif", 6))
break; __Process(str);
} puts("-----------------------------------------------------------"); freopen("/usr/include/asm-generic/errno.h", "r", stdin); // 读文件
while (1)
{
char str[1024] = {0};
fgets(str, sizeof(str), stdin); if (0 == strncmp(str, "#endif", 6))
break; __Process(str);
}
}

参考资料

Linux 系统错误码 errno 剖析的更多相关文章

  1. Linux系统错误码对照表

    C Name Value Description EPERM 1 Operation not permitted ENOENT 2 No such file or directory ESRCH 3 ...

  2. linux系统错误码大全

    #define EPERM 1 /* Operation not permitted */ #define ENOENT 2 /* No such file or directory */ #defi ...

  3. Redis 源码简洁剖析 09 - Reactor 模型

    Reactor 模型 事件驱动框架 Redis 如何实现 Reactor 模型 事件的数据结构:aeFileEvent 主循环:aeMain 函数 事件捕获与分发:aeProcessEvents 函数 ...

  4. Redis 源码简洁剖析 10 - aeEventLoop 及事件

    aeEventLoop IO 事件处理 IO 事件创建 读事件处理 写事件处理 时间事件处理 时间事件定义 时间事件创建 时间事件回调函数 时间事件的触发处理 参考链接 Redis 源码简洁剖析系列 ...

  5. TCP/IP 某些最常见的错误原因码 (errno)列表

    对于在基于 UNIX 的环境中的 TCP/IP 用户,下表列出了某些最常见的错误原因码 (errno).它不是完整的错误列表.可以在文件 /usr/include/sys/errno.h 中找到 Er ...

  6. TCP/IP 最常见的错误原因码 (errno)列表

    对于在基于 UNIX 的环境中的 TCP/IP 用户,下表列出了某些最常见的错误原因码 (errno).它不是完整的错误列表.可以在文件 /usr/include/sys/errno.h 中找到 Er ...

  7. linux lcd设备驱动剖析四

    在"linux lcd设备驱动剖析二"文章中,我们详细分析了s3c24xxfb_probe函数. 文章链接:http://blog.csdn.net/lwj103862095/ar ...

  8. linux lcd设备驱动剖析一

    s3c2440 lcd驱动源码文件是:drivers/video/s3c2410fb.c 看驱动源码首先当然是先看入口函数,这里是s3c2410fb_init函数 [cpp] view plain? ...

  9. libevent源码深度剖析十一

    libevent源码深度剖析十一 ——时间管理 张亮 为了支持定时器,Libevent必须和系统时间打交道,这一部分的内容也比较简单,主要涉及到时间的加减辅助函数.时间缓存.时间校正和定时器堆的时间值 ...

  10. libevent源码深度剖析十

    libevent源码深度剖析十 ——支持I/O多路复用技术 张亮 Libevent的核心是事件驱动.同步非阻塞,为了达到这一目标,必须采用系统提供的I/O多路复用技术,而这些在Windows.Linu ...

随机推荐

  1. postman测试Integer[]数组

    背景说明:在做批量删除列表数据的时候,前端发送数组格式给后端,后端使用数组格式(Integer[] ids)接受,需要使用postman测试结果. @ApiOperation("管理系统-删 ...

  2. 解决SystemExit: 2,args = parser.parse_args() 的问题,

    报错: File "/home/barry/PycharmProjects/EEPC/detect.py", line 283, in parse_opt opt = parser ...

  3. 【五】强化学习之Sarsa、Qlearing详细讲解----PaddlePaddlle【PARL】框架{飞桨}

    相关文章: [一]飞桨paddle[GPU.CPU]安装以及环境配置+python入门教学 [二]-Parl基础命令 [三]-Notebook.&pdb.ipdb 调试 [四]-强化学习入门简 ...

  4. Win32汇编:字符串浮点数运算过程

    整理复习汇编语言的知识点,以前在学习<Intel汇编语言程序设计 - 第五版>时没有很认真的整理笔记,主要因为当时是以学习理解为目的没有整理的很详细,这次是我第三次阅读此书,每一次阅读都会 ...

  5. Linux虚拟机追加扩展磁盘

    一.使用VMware给虚拟机追加磁盘 使用VMware打开虚拟机设置对话框,选择硬盘,点击右侧的扩展按钮,输入扩展后的磁盘容量. 点击扩展按钮.提示磁盘已成功扩展. 二.对闲置的空间进行分区 上面扩展 ...

  6. Java并发(十四)----悲观互斥与乐观重试

    1. 悲观互斥 互斥实际是悲观锁的思想 例如,有下面取款的需求 interface Account {    // 获取余额    Integer getBalance(); ​    // 取款   ...

  7. 使用SecureCRT的按钮实现快速查询

    背景:有这么个日常运维场景,客户因管理需求,不允许在服务器上部署任何自动化的脚本,需要人工登录到机器上查询ASM磁盘组的使用率情况,有上百套环境. 使用的工具是SecureCRT,如何提升一些效率呢? ...

  8. Jackson objectMapper.readValue 方法 详解

    直接说结论方便一目了然: 1. 简单的直接Bean.class 2. 复杂的用 TypeReference 这样就完事了. public class TestMain2 { public static ...

  9. Kafka的ACK机制

    Kafka的ack机制,指的是producer的消息发送确认机制,这直接影响到Kafka集群的吞吐量和消息可靠性.而吞吐量和可靠性就像硬币的两面,两者不可兼得,只能平衡. ACK有3个可选值,分别是1 ...

  10. 从零开始的react入门教程(八),redux起源与基础用法

    壹 ❀ 引 我们在从零开始的react入门教程(七),react中的状态提升,我们为什么需要使用redux一文中介绍了react的状态提升,对于不同组件之间状态需要通信时,将状态提升至两个组件共有的最 ...