博客搬家,原地址:https://langzi989.github.io/2017/05/22/Unix错误处理/
当Unix系统函数出错的时候,通常会返回一个负值,同时整型变量errno通常被设置为具有特定信息的值。例如当使用open打开文件的时候,若当前文件不存在,此时open的返回值为-1,errno被设置为2(ENOENT)。
系统函数出错的返回值不一定为负数,是根据具体函数具体定义的,如当系统函数返回一个指针时,若出错,将会返回NULL。
Linux系统中errno.h中定义了一系列的错误宏,他们之处了不同错误对应的错误ID,为整型变量,可被赋值。
关于errno需要注意的两点:
- 如果没出错,errno将不会被进程设置,所以一般当利用函数返回值确认已经出错的时候,再去查看相应的errno
- 任何函数不会讲errno的值设置为0,而且在errno.h中定义的所有宏定义都不为0
Unix错误处理的两个相关函数
strerror函数
函数原型
#include <string.h>
char* strerror(int errno);
函数功能
此函数的功能为将errno转化为其对应的具体错误信息。
示例代码
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main() {
int fd = open("data");
if (fd == -1) {
printf("%s", strerror(errno));
}
}
perror函数
函数原型
#include <stdio.h>
void perror(const char* msg);
函数功能
perror基于当前errno的值,在标准错误流上输出一个出错信息。输出内容首先输出msg所指的字符串,然后一个冒号,空格,接着是errno对应的错误字符串,最后是一个换行符。
示例代码
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int fd = open("data");
if (fd == -1) {
printf("%s", strerror(errno));
perror(argv[0]);
}
}
一些特殊的错误
EAGAIN,EWOULDBLOCK和EINTR
在Linux环境下开发经常会碰到很多错误(设置errno),其中EAGAIN是其中比较常见的一个错误(比如用在非阻塞操作中)。
从字面上来看,是提示再试一次。这个错误经常出现在当应用程序进行一些非阻塞(non-blocking)操作(对文件或socket)的时候。
例如,以 O_NONBLOCK的标志打开文件/socket/FIFO,如果你连续做read操作而没有数据可读。此时程序不会阻塞起来等待数据准备就绪返 回,
read函数会返回一个错误EAGAIN,提示你的应用程序现在没有数据可读请稍后再试。
又例如,当一个系统调用(比如fork)因为没有足够的资源(比如虚拟内存)而执行失败,返回EAGAIN提示其再调用一次(也许下次就能成功)。
EAGAIN:Linux - 非阻塞socket编程处理EAGAIN错误
在linux进行非阻塞的socket接收数据时经常出现Resource temporarily unavailable,errno代码为11(EAGAIN),这是什么意思?
这表明你在非阻塞模式下调用了阻塞操作,在该操作没有完成就返回这个错误,这个错误不会破坏socket的同步,不用管它,下次循环接着recv就可以。
对非阻塞socket而言,EAGAIN不是一种错误。在VxWorks和Windows上,EAGAIN的名字叫做EWOULDBLOCK。
另外,如果出现EINTR即errno为4,错误描述Interrupted system call,操作也应该继续。
最后,如果recv的返回值为0,那表明连接已经断开,我们的接收操作也应该结束。
错误恢复
我们可以将errno.h中定义的错误分为两种,分别是致命的和非致命的,对于致命性错误,无法执行恢复操作。对于非致命性错误,大多数来说是暂时的。
对于非致命性错误,最常用的做法就是延迟一段时间,然后重试。例如当错误表示网络不可用,这时我们将可以通过延迟一段时间,进行重新连接。
errno宏定义及相应解释
124 EMEDIUMTYPE Wrong medium type
123 ENOMEDIUM No medium found
122 EDQUOT Disk quota exceeded
121 EREMOTEIO Remote I/O error
120 EISNAM Is a named type file
119 ENAVAIL No XENIX semaphores available
118 ENOTNAM Not a XENIX named type file
117 EUCLEAN Structure needs cleaning
116 ESTALE Stale NFS file handle
115 EINPROGRESS +Operation now in progress
114 EALREADY Operation already in progress
113 EHOSTUNREACH No route to host
112 EHOSTDOWN Host is down
111 ECONNREFUSED Connection refused
110 ETIMEDOUT +Connection timed out
109 ETOOMANYREFS Too many references: cannot splice
108 ESHUTDOWN Cannot send after transport endpoint shutdown
107 ENOTCONN Transport endpoint is not connected
106 EISCONN Transport endpoint is already connected
105 ENOBUFS No buffer space available
104 ECONNRESET Connection reset by peer
103 ECONNABORTED Software caused connection abort
102 ENETRESET Network dropped connection on reset
101 ENETUNREACH Network is unreachable
100 ENETDOWN Network is down
99 EADDRNOTAVAIL Cannot assign requested address
98 EADDRINUSE Address already in use
97 EAFNOSUPPORT Address family not supported by protocol
96 EPFNOSUPPORT Protocol family not supported
95 EOPNOTSUPP Operation not supported
94 ESOCKTNOSUPPORT Socket type not supported
93 EPROTONOSUPPORT Protocol not supported
92 ENOPROTOOPT Protocol not available
91 EPROTOTYPE Protocol wrong type for socket
90 EMSGSIZE +Message too long
89 EDESTADDRREQ Destination address required
88 ENOTSOCK Socket operation on non-socket
87 EUSERS Too many users
86 ESTRPIPE Streams pipe error
85 ERESTART Interrupted system call should be restarted
84 EILSEQ Invalid or incomplete multibyte or wide character
83 ELIBEXEC Cannot exec a shared library directly
82 ELIBMAX Attempting to link in too many shared libraries
81 ELIBSCN .lib section in a.out corrupted
80 ELIBBAD Accessing a corrupted shared library
79 ELIBACC Can not access a needed shared library
78 EREMCHG Remote address changed
77 EBADFD File descriptor in bad state
76 ENOTUNIQ Name not unique on network
75 EOVERFLOW Value too large for defined data type
74 EBADMSG +Bad message
73 EDOTDOT RFS specific error
72 EMULTIHOP Multihop attempted
71 EPROTO Protocol error
70 ECOMM Communication error on send
69 ESRMNT Srmount error
68 EADV Advertise error
67 ENOLINK Link has been severed
66 EREMOTE Object is remote
65 ENOPKG Package not installed
64 ENONET Machine is not on the network
63 ENOSR Out of streams resources
62 ETIME Timer expired
61 ENODATA No data available
60 ENOSTR Device not a stream
59 EBFONT Bad font file format
57 EBADSLT Invalid slot
56 EBADRQC Invalid request code
55 ENOANO No anode
54 EXFULL Exchange full
53 EBADR Invalid request descriptor
52 EBADE Invalid exchange
51 EL2HLT Level 2 halted
50 ENOCSI No CSI structure available
49 EUNATCH Protocol driver not attached
48 ELNRNG Link number out of range
47 EL3RST Level 3 reset
46 EL3HLT Level 3 halted
45 EL2NSYNC Level 2 not synchronized
44 ECHRNG Channel number out of range
43 EIDRM Identifier removed
42 ENOMSG No message of desired type
40 ELOOP Too many levels of symbolic links
39 ENOTEMPTY +Directory not empty
38 ENOSYS +Function not implemented
37 ENOLCK +No locks available
36 ENAMETOOLONG +File name too long
35 EDEADLK +Resource deadlock avoided
34 ERANGE +Numerical result out of range
33 EDOM +Numerical argument out of domain
32 EPIPE +Broken pipe
31 EMLINK +Too many links
30 EROFS +Read-only file system
29 ESPIPE +Illegal seek
28 ENOSPC +No space left on device
27 EFBIG +File too large
26 ETXTBSY Text file busy
25 ENOTTY +Inappropriate ioctl for device
24 EMFILE +Too many open files
23 ENFILE +Too many open files in system
22 EINVAL +Invalid argument
21 EISDIR +Is a directory
20 ENOTDIR +Not a directory
19 ENODEV +No such device
18 EXDEV +Invalid cross-device link
17 EEXIST +File exists
16 EBUSY +Device or resource busy
15 ENOTBLK Block device required
14 EFAULT +Bad address
13 EACCES +Permission denied
12 ENOMEM +Cannot allocate memory
11 EAGAIN +Resource temporarily unavailable
10 ECHILD +No child processes
9 EBADF +Bad file descriptor
8 ENOEXEC +Exec format error
7 E2BIG +Argument list too long
6 ENXIO +No such device or address
5 EIO +Input/output error
4 EINTR +Interrupted system call
3 ESRCH +No such process
2 ENOENT +No such file or directory
1 EPERM +Operation not permitted
0 Success