名称
errno - 最后一次错误码
简介
#include <errno.h>
描述
头文件<errno.h>定义了整型变量errno,当系统调用和一些库函数出错时,会设置errno来表明出错原因。
errno
只有当调用的返回值表明出错时(例如,大多数系统调用返回-1;大多数库函数返回-1或NULL),errno的值才有意义;成功执行的函数允许改变errno。没有任何系统调用或库函数会将errno设置为零。
对于某些系统调用和库函数(例如,getpriority(2)),-1是成功返回的有效值。在这种情况下,可以通过在调用前将errno设置为零,然后在调用返回可能表示出错的状态时,检查errno是否有非零值,来区分成功返回和出错返回。
errno被ISO C标准定义为可修改的lvalue,类型为int,且不能显式声明;errno可能是一个宏。errno是线程局部的;在一个线程中设置它不会影响其他线程中的值。
错误编号和名称
有效的错误编号都是正数。<errno.h>头文件为可能出现的错误编号定义了符号名称。
POSIX.1规定的各种错误名称必须具有不同的值,但EAGAIN和EWOULDBLOCK除外,它们可能相同。在Linux上,这两种在所有架构上都有相同的值。
不同的UNIX系统,甚至Linux上不同架构对应的错误编号也会有所不同。因此,下面列出的错误名称列表中没有包含数值。可以使用perror(3)和strerror(3)函数将这些名称转换为对应的文本错误消息。
在任何特定的Linux系统上,都可以使用errno(1)命令(moreutils软件包的一部分)来获取所有符号错误名称和对应的错误编号列表:
$ errno -l
EPERM 1 Operation not permitted
ENOENT 2 No such file or directory
ESRCH 3 No such process
EINTR 4 Interrupted system call
EIO 5 Input/output error
...
errno(1)命令还可以用来查找单独的错误编号和名称,以及使用错误描述中的字符串来搜索错误,例如:
$ errno 2
ENOENT 2 No such file or directory
$ errno ESRCH
ESRCH 3 No such process
$ errno -s permission
EACCES 13 Permission denied
错误名称列表
在下面的符号错误名称列表中,各种名称标记如下:
* POSIX.1-2001:该名称由POSIX.1-2001定义,并且在后来的POSIX.1版本中也有定义,除非另有说明。
* POSIX.1-2008:该名称在POSIX.1-2008中定义,但在早期的POSIX.1标准中不存在。
* C99:该名称由C99定义。
下面是在Linux上定义的符号错误名称列表:
E2BIG 参数列表过长(POSIX.1-2001)。
EACCES 禁止访问(POSIX.1-2001)。
EADDRINUSE
地址已在使用中(POSIX.1-2001)。
EADDRNOTAVAIL
地址不可用(POSIX.1-2001)。
EAFNOSUPPORT
不支持的地址族(POSIX.1-2001)。
EAGAIN 资源暂时不可用(可能与EWOULDBLOCK相同值)(POSIX.1-2001)。
EALREADY
连接已在进行中(POSIX.1-2001)。
EBADE 无效的交换。
EBADF 无效的文件描述符(POSIX.1-2001)。
EBADFD 文件描述符状态不佳。
EBADMSG
无效的消息(POSIX.1-2001)。
EBADR 无效的请求描述符。
EBADRQC
无效的请求代码。
EBADSLT
无效的插槽。
EBUSY 设备或资源正忙(POSIX.1-2001)。
ECANCELED
操作已取消(POSIX.1-2001)。
ECHILD 无子进程(POSIX.1-2001)。
ECHRNG 通道编号超出范围。
ECOMM 发送时通信错误。
ECONNABORTED
连接已中止(POSIX.1-2001)。
ECONNREFUSED
连接被拒绝(POSIX.1-2001)。
ECONNRESET
连接已重置(POSIX.1-2001)。
EDEADLK
避免资源死锁(POSIX.1-2001)。
EDEADLOCK
在大多数架构上,这是EDEADLK的同义词。在某些架构(例如,Linux MIPS、PowerPC、SPARC)上,它是一个单独的错误代码“文件锁定死锁错误”。
EDESTADDRREQ
需要目的地址(POSIX.1-2001)。
EDOM 数学函数的参数超出定义域(POSIX.1,C99)。
EDQUOT 超出磁盘配额(POSIX.1-2001)。
EEXIST 文件已存在(POSIX.1-2001)。
EFAULT 坏地址(POSIX.1-2001)。
EFBIG 文件过大(POSIX.1-2001)。
EHOSTDOWN
主机已关闭。
EHOSTUNREACH
主机不可达(POSIX.1-2001)。
EHWPOISON
内存页存在硬件错误。
EIDRM 标识符已被移除(POSIX.1-2001)。
EILSEQ 无效或不完整的多字节或宽字符(POSIX.1,C99)。
此处显示的是glibc的错误描述;在POSIX.1中,此错误被描述为“Illegal byte sequence”。
EINPROGRESS
操作正在进行中(POSIX.1-2001)。
EINTR 被中断的函数调用(POSIX.1-2001);参见signal(7)。
EINVAL 无效的参数(POSIX.1-2001)。
EIO 输入/输出错误(POSIX.1-2001)。
EISCONN
套接字已连接(POSIX.1-2001)。
EISDIR 是一个目录(POSIX.1-2001)。
EISNAM 是一个命名类型文件。
EKEYEXPIRED
密钥已过期。
EKEYREJECTED
密钥被服务拒绝。
EKEYREVOKED
密钥已被撤销。
EL2HLT 级别2已停止。
EL2NSYNC
级别2未同步。
EL3HLT 级别3已停止。
EL3RST 级别3已重置。
ELIBACC
无法访问所需的共享库。
ELIBBAD
访问损坏的共享库。
ELIBMAX
尝试链接过多的共享库。
ELIBSCN
a.out中的.lib部分已损坏
ELIBEXEC
无法直接执行共享库。
ELNRANGE
链接编号超出范围。
ELOOP 符号链接层级过多(POSIX.1-2001)。
EMEDIUMTYPE
错误的介质类型。
EMFILE 打开的文件过多(POSIX.1-2001)。通常是由超出getrlimit(2)中描述的RLIMIT_NOFILE资源限制所导致。也可能是因为超出了/proc/sys/fs/nr_open中指定的限制。
EMLINK 链接过多(POSIX.1-2001)。
EMSGSIZE
消息过长(POSIX.1-2001)。
EMULTIHOP
尝试多跳(POSIX.1-2001)。
ENAMETOOLONG
文件名过长(POSIX.1-2001)。
ENETDOWN
网络已关闭(POSIX.1-2001)。
ENETRESET
网络已重置连接(POSIX.1-2001)。
ENETUNREACH
网络不可达(POSIX.1-2001)。
ENFILE 系统中打开的文件过多(POSIX.1-2001)。在Linux上,这可能是遇到了/proc/sys/fs/file-max限制(参见proc(5))。
ENOANO 无anode。
ENOBUFS
无缓冲区空间可用(POSIX.1 (XSI STREAMS选项))。
ENODATA
命名的属性不存在,或者进程无权访问此属性;参见xattr(7)。
在POSIX.1-2001 (XSI STREAMS选项)中,此错误被描述为“STREAM头读队列上没有可用的消息”。
ENODEV 无此设备(POSIX.1-2001)。
ENOENT 无此文件或目录(POSIX.1-2001)。
通常,当指定的路径名不存在,或者路径名目录前缀中的某个组件不存在,或者指定的路径名是一个悬空的符号链接时,会出现此错误。
ENOEXEC
执行格式错误(POSIX.1-2001)。
ENOKEY 所需的密钥不可用。
ENOLCK 无锁可用(POSIX.1-2001)。
ENOLINK
链接已被切断(POSIX.1-2001)。
ENOMEDIUM
未找到介质。
ENOMEM 内存不足/无法分配内存(POSIX.1-2001)。
ENOMSG 无所需类型的消息(POSIX.1-2001)。
ENONET 机器未联网。
ENOPKG 包未安装。
ENOPROTOOPT
协议不可用(POSIX.1-2001)。
ENOSPC 设备上无剩余空间(POSIX.1-2001)。
ENOSR 无STREAM资源(POSIX.1 (XSI STREAMS选项))。
ENOSTR 不是STREAM(POSIX.1 (XSI STREAMS选项))。
ENOSYS 函数未实现(POSIX.1-2001)。
ENOTBLK
需要块设备。
ENOTCONN
套接字未连接(POSIX.1-2001)。
ENOTDIR
不是目录(POSIX.1-2001)。
ENOTEMPTY
目录不为空(POSIX.1-2001)。
ENOTRECOVERABLE
状态不可恢复(POSIX.1-2008)。
ENOTSOCK
不是套接字(POSIX.1-2001)。
ENOTSUP
操作不支持(POSIX.1-2001)。
ENOTTY 不适当的I/O控制操作(POSIX.1-2001)。
ENOTUNIQ
网络上的名称不唯一。
ENXIO 无此设备或地址(POSIX.1-2001)。
EOPNOTSUPP
套接字上不支持的操作(POSIX.1-2001)。
(在Linux上,ENOTSUP和EOPNOTSUPP的值相同,但根据POSIX.1,这些错误值应该是不同的。)
EOVERFLOW
值太大,无法存储在数据类型中(POSIX.1-2001)。
EOWNERDEAD
所有者已死(POSIX.1-2008)。
EPERM 操作不被允许(POSIX.1-2001)。
EPFNOSUPPORT
不支持的协议族。
EPIPE 破损的管道(POSIX.1-2001)。
EPROTO 协议错误(POSIX.1-2001)。
EPROTONOSUPPORT
不支持的协议(POSIX.1-2001)。
EPROTOTYPE
套接字的协议类型错误(POSIX.1-2001)。
ERANGE 结果太大(POSIX.1,C99)。
EREMCHG
远程地址已更改。
EREMOTE
对象是远程的。
EREMOTEIO
远程I/O错误。
ERESTART
被中断的系统调用应重新启动。
ERFKILL
由于RF-kill,操作无法执行。
EROFS 只读文件系统(POSIX.1-2001)。
ESHUTDOWN
传输端点关闭后无法发送。
ESPIPE 无效的seek(POSIX.1-2001)。
ESOCKTNOSUPPORT
不支持的套接字类型。
ESRCH 无此进程(POSIX.1-2001)。
ESTALE 过时的文件句柄(POSIX.1-2001)。
此错误可能出现在NFS以及其他文件系统中。
ESTRPIPE
Streams管道错误。
ETIME 定时器已到期(POSIX.1 (XSI STREAMS选项))。
(POSIX.1说“STREAM ioctl(2)超时”。)
ETIMEDOUT
连接超时(POSIX.1-2001)。
ETOOMANYREFS
引用过多,无法拼接。
ETXTBSY
文本文件正忙(POSIX.1-2001)。
EUCLEAN
结构需要清理。
EUNATCH
协议驱动未连接。
EUSERS 用户过多。
EWOULDBLOCK
操作将阻塞(可能与EAGAIN相同值)(POSIX.1-2001)。
EXDEV 不正确的链接(POSIX.1-2001)。
EXFULL 交换区已满。
说明
一个常见的错误是这样写代码:
if (somecall() == -1) {
printf("somecall() failed\n");
if (errno == ...) { ... }
}
此时errno的值可能已经被printf(3)改变了,不再是从somecall()返回时的值。如果需要在库函数调用后保留errno的值,必须将其保存起来:
if (somecall() == -1) {
int errsv = errno;
printf("somecall() failed\n");
if (errsv == ...) { ... }
}
注意,POSIX线程API在出错时不会设置errno。相反,它们会将错误编号作为函数结果返回。这些错误编号与其它API在errno中返回的错误编号具有相同的含义。
在一些古老的系统上,<errno.h>不存在或者未声明errno,因此需要手动声明errno(即extern int errno)。不要这样做。这种做法很久以前就不再必要了,而且会在现代版本的C库中引发问题。
另请参阅
errno(1), err(3), error(3), perror(3), strerror(3)