linux errno详解
原文地址:http://blog.csdn.net/scaleqiao/article/details/46056349之所以写这篇文章,是因为我踩过它的坑。背景是我在做一个项目时,其中有一部分是在QEMU中调用cephfs的接口,期间有个函数ceph_lstat(),明明返回了错误的值,但QEMU缺认为这个调用没用问题,当时我没有觉得这个函数本身有问题,所以一直在debug别的东西。整整
原文地址:http://blog.csdn.net/scaleqiao/article/details/46056349
之所以写这篇文章,是因为我踩过它的坑。背景是我在做一个项目时,其中有一部分是在QEMU中调用cephfs的接口,期间有个函数ceph_lstat(),明明返回了错误的值,但QEMU缺认为这个调用没用问题,当时我没有觉得这个函数本身有问题,所以一直在debug别的东西。整整花了一周,终于找到了原因:QEMU中有些错误处理依赖于errno的值,但cephfs的接口在发生error时不会去设置它,我勒个去,当时我就泪奔了。。。鉴于我惨痛的经历,所以在这里将errno的信息整理一下,方便大家了解。另外也希望给大家提一个醒,当你得程序涉及系统调用时,记得要考虑errno这个隐形的杀手。
1. errno是个什么东西?
- The <errno.h> header file defines the integer variable errno, which
- is set by system calls and some library functions in the event of an
- error to indicate what went wrong. Its value is significant only
- when the return value of the call indicated an error (i.e., -1 from
- most system calls; -1 or NULL from most library functions); a
- function that succeeds is allowed to change errno.
- Valid error numbers are all nonzero; errno is never set to zero by
- any system call or library function.
- For some system calls and library functions (e.g., getpriority(2)),
- -1 is a valid return on success. In such cases, a successful return
- can be distinguished from an error return by setting errno to zero
- before the call, and then, if the call returns a status that
- indicates that an error may have occurred, checking to see if errno
- has a nonzero value.
- errno is defined by the ISO C standard to be a modifiable lvalue of
- type int, and must not be explicitly declared; errno may be a macro.
- errno is thread-local; setting it in one thread does not affect its
- value in any other thread.
1)errno是一个整型变量,当系统调用和一些库函数发生错误时会通过设置errno的值来告诉调用者出了什么问题。
2)errno的有效值都是非零的。(这个manpage有个悖论,第二段中说,errno从来不能被设为0,而在第三段又说有些接口会将其设置为0)
3)errno在ISO C标准中定义的,它可能是一个宏并且不能被显示声明(也就是重新定义)。
4)errno是线程安全的,在一个线程中设置它,不会影响别的线程对它的使用。这一点很重要,不知道有没有像我之前有过这样的问题:看起来errno像是一个全局的变量,应该不是线程安全的吧?看了这个之后,就有答案了,errno是thread-local的,也就是每个线程都有一个。
2. errno的定义
errno被定义在/usr/include/bits/errno.h文件中:
- # if !defined _LIBC || defined _LIBC_REENTRANT
- /* When using threads, errno is a per-thread value. */
- # define errno (*__errno_location ())
- # endif
- # endif /* !__ASSEMBLER__ */
- #endif /* _ERRNO_H */
- [root@cephenv ~]# cat testenv.c
- #include <stdio.h>
- #include <errno.h>
- int main( void )
- {
- #ifndef __ASSEMBLER__
- printf( "__ASSEMBLER__ is not defined\n");
- #else
- printf( "__ASSEMBLER__ is defined\n");
- #endif
- #ifndef __LIBC
- printf( "__LIBC is not defined\n");
- #else
- printf( "__LIBC is defined\n");
- #endif
- #ifndef _LIBC_REENTRANT
- printf( "_LIBC_REENTRANT is not defined\n");
- #else
- printf( "_LIBC_REENTRANT is defined\n");
- #endif
- return 0;
- }
- [root@cephenv ~]# ./a.out
- __ASSEMBLER__ is not defined
- __LIBC is not defined
- _LIBC_REENTRANT is not defined
3. errno各返回值的含义:
它的每个值的含义定义在/usr/include/asm-generic/errno-base.h文件中(貌似不全啊),也可以通过strerror写一个小程序来输出错误码对应的解释:
- [root@cephenv ~]# cat printerrno.c
- #include <stdio.h>
- #include <string.h>
- int main(int argc, char *argv[])
- {
- int i = 0;
- for (; i < 256; i++)
- printf("errno %d: %s\n", i, strerror(i));
- return 0;
- }
- [root@cephenv ~]# ./a.out
- errno 0: Success
- errno 1: Operation not permitted
- errno 2: No such file or directory
- errno 3: No such process
- errno 4: Interrupted system call
- errno 5: Input/output error
- errno 6: No such device or address
- errno 7: Argument list too long
- errno 8: Exec format error
- errno 9: Bad file descriptor
- errno 10: No child processes
- errno 11: Resource temporarily unavailable
- errno 12: Cannot allocate memory
- errno 13: Permission denied
- errno 14: Bad address
- errno 15: Block device required
- errno 16: Device or resource busy
- errno 17: File exists
- errno 18: Invalid cross-device link
- errno 19: No such device
- errno 20: Not a directory
- errno 21: Is a directory
- errno 22: Invalid argument
- errno 23: Too many open files in system
- errno 24: Too many open files
- errno 25: Inappropriate ioctl for device
- errno 26: Text file busy
- errno 27: File too large
- errno 28: No space left on device
- errno 29: Illegal seek
- errno 30: Read-only file system
- errno 31: Too many links
- errno 32: Broken pipe
- errno 33: Numerical argument out of domain
- errno 34: Numerical result out of range
- errno 35: Resource deadlock avoided
- errno 36: File name too long
- errno 37: No locks available
- errno 38: Function not implemented
- errno 39: Directory not empty
- errno 40: Too many levels of symbolic links
- errno 41: Unknown error 41
- errno 42: No message of desired type
- errno 43: Identifier removed
- errno 44: Channel number out of range
- errno 45: Level 2 not synchronized
- errno 46: Level 3 halted
- errno 47: Level 3 reset
- errno 48: Link number out of range
- errno 49: Protocol driver not attached
- errno 50: No CSI structure available
- errno 51: Level 2 halted
- errno 52: Invalid exchange
- errno 53: Invalid request descriptor
- errno 54: Exchange full
- errno 55: No anode
- errno 56: Invalid request code
- errno 57: Invalid slot
- errno 58: Unknown error 58
- errno 59: Bad font file format
- errno 60: Device not a stream
- errno 61: No data available
- errno 62: Timer expired
- errno 63: Out of streams resources
- errno 64: Machine is not on the network
- errno 65: Package not installed
- errno 66: Object is remote
- errno 67: Link has been severed
- errno 68: Advertise error
- errno 69: Srmount error
- errno 70: Communication error on send
- errno 71: Protocol error
- errno 72: Multihop attempted
- errno 73: RFS specific error
- errno 74: Bad message
- errno 75: Value too large for defined data type
- errno 76: Name not unique on network
- errno 77: File descriptor in bad state
- errno 78: Remote address changed
- errno 79: Can not access a needed shared library
- errno 80: Accessing a corrupted shared library
- errno 81: .lib section in a.out corrupted
- errno 82: Attempting to link in too many shared libraries
- errno 83: Cannot exec a shared library directly
- errno 84: Invalid or incomplete multibyte or wide character
- errno 85: Interrupted system call should be restarted
- errno 86: Streams pipe error
- errno 87: Too many users
- errno 88: Socket operation on non-socket
- errno 89: Destination address required
- errno 90: Message too long
- errno 91: Protocol wrong type for socket
- errno 92: Protocol not available
- errno 93: Protocol not supported
- errno 94: Socket type not supported
- errno 95: Operation not supported
- errno 96: Protocol family not supported
- errno 97: Address family not supported by protocol
- errno 98: Address already in use
- errno 99: Cannot assign requested address
- errno 100: Network is down
- errno 101: Network is unreachable
- errno 102: Network dropped connection on reset
- errno 103: Software caused connection abort
- errno 104: Connection reset by peer
- errno 105: No buffer space available
- errno 106: Transport endpoint is already connected
- errno 107: Transport endpoint is not connected
- errno 108: Cannot send after transport endpoint shutdown
- errno 109: Too many references: cannot splice
- errno 110: Connection timed out
- errno 111: Connection refused
- errno 112: Host is down
- errno 113: No route to host
- errno 114: Operation already in progress
- errno 115: Operation now in progress
- errno 116: Stale file handle
- errno 117: Structure needs cleaning
- errno 118: Not a XENIX named type file
- errno 119: No XENIX semaphores available
- errno 120: Is a named type file
- errno 121: Remote I/O error
- errno 122: Disk quota exceeded
- errno 123: No medium found
- errno 124: Wrong medium type
- errno 125: Operation canceled
- errno 126: Required key not available
- errno 127: Key has expired
- errno 128: Key has been revoked
- errno 129: Key was rejected by service
- errno 130: Owner died
- errno 131: State not recoverable
- errno 132: Operation not possible due to RF-kill
其实也就两条:
1)当使用系统调用和库函数时,除了函数的返回值,记得还要考虑errno的值啊。
2)并不是所有的系统调用活着库函数都会设置errno的值,如果你的程序对它有依赖,需要开发人员在接口错误处理中,手工设置。
更多推荐
所有评论(0)