之所以写这篇文章,是因为我踩过它的坑。背景是我在做一个项目时,其中有一部分是在QEMU中调用cephfs的接口,期间有个函数ceph_lstat(),明明返回了错误的值,但QEMU缺认为这个调用没用问题,当时我没有觉得这个函数本身有问题,所以一直在debug别的东西。整整花了一周,终于找到了原因:QEMU中有些错误处理依赖于errno的值,但cephfs的接口在发生error时不会去设置它,我勒个去,当时我就泪奔了。。。鉴于我惨痛的经历,所以在这里将errno的信息整理一下,方便大家了解。另外也希望给大家提一个醒,当你得程序涉及系统调用时,记得要考虑errno这个隐形的杀手。
1. errno是个什么东西?
The 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.
以上是linux中关于errno的manpage,大意可以概括为:
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 */
也就是说当编译器检查没有定义_LIBC或者定义了_LIBC_REENTRANT,errno就是线程安全的。可以通过如下程序来判断你的系统中这些宏是否被定义:
[root@cephenv ~]# cat testenv.c
#include
#include
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
由于 __LIBC没有被定义,所以errno是线程安全的。其实,通过gcc编译一般的应用程序时__LIBC都是没有定义的。
3. errno各返回值的含义:
它的每个值的含义定义在/usr/include/asm-generic/errno-base.h文件中(貌似不全啊),也可以通过strerror写一个小程序来输出错误码对应的解释:
[root@cephenv ~]# cat printerrno.c
#include
#include
int main(int argc, char *argv[])
{
int i = 0;
for (; i < 256; i++)
printf("errno %d: %s\n", i, strerror(i));
return 0;
}
趁机也贴出每个errno的解释:
[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
4. errno使用的注意事项。