文章地址:
#ifndef _I386_ERRNO_H
#define _I386_ERRNO_H
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Arg list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */
#define EDEADLK 35 /* Resource deadlock would occur */
#define ENAMETOOLONG 36 /* File name too long */
#define ENOLCK 37 /* No record locks available */
#define ENOSYS 38 /* Function not implemented */
#define ENOTEMPTY 39 /* Directory not empty */
#define ELOOP 40 /* Too many symbolic links encountered */
#define EWOULDBLOCK EAGAIN /* Operation would block */
#define ENOMSG 42 /* No message of desired type */
#define EIDRM 43 /* Identifier removed */
#define ECHRNG 44 /* Channel number out of range */
#define EL2NSYNC 45 /* Level 2 not synchronized */
#define EL3HLT 46 /* Level 3 halted */
#define EL3RST 47 /* Level 3 reset */
#define ELNRNG 48 /* Link number out of range */
#define EUNATCH 49 /* Protocol driver not attached */
#define ENOCSI 50 /* No CSI structure available */
#define EL2HLT 51 /* Level 2 halted */
#define EBADE 52 /* Invalid exchange */
#define EBADR 53 /* Invalid request descriptor */
#define EXFULL 54 /* Exchange full */
#define ENOANO 55 /* No anode */
#define EBADRQC 56 /* Invalid request code */
#define EBADSLT 57 /* Invalid slot */
#define EDEADLOCK EDEADLK
#define EBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* No data available */
#define ETIME 62 /* Timer expired */
#define ENOSR 63 /* Out of streams resources */
#define ENONET 64 /* Machine is not on the network */
#define ENOPKG 65 /* Package not installed */
#define EREMOTE 66 /* Object is remote */
#define ENOLINK 67 /* Link has been severed */
#define EADV 68 /* Advertise error */
#define ESRMNT 69 /* Srmount error */
#define ECOMM 70 /* Communication error on send */
#define EPROTO 71 /* Protocol error */
#define EMULTIHOP 72 /* Multihop attempted */
#define EDOTDOT 73 /* RFS specific error */
#define EBADMSG 74 /* Not a data message */
#define EOVERFLOW 75 /* Value too large for defined data type */
#define ENOTUNIQ 76 /* Name not unique on network */
#define EBADFD 77 /* File descriptor in bad state */
#define EREMCHG 78 /* Remote address changed */
#define ELIBACC 79 /* Can not access a needed shared library */
#define ELIBBAD 80 /* Accessing a corrupted shared library */
#define ELIBSCN 81 /* .lib section in a.out corrupted */
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
#define EILSEQ 84 /* Illegal byte sequence */
#define ERESTART 85 /* Interrupted system call should be restarted */
#define ESTRPIPE 86 /* Streams pipe error */
#define EUSERS 87 /* Too many users */
#define ENOTSOCK 88 /* Socket operation on non-socket */
#define EDESTADDRREQ 89 /* Destination address required */
#define EMSGSIZE 90 /* Message too long */
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
#define ENOPROTOOPT 92 /* Protocol not available */
#define EPROTONOSUPPORT 93 /* Protocol not supported */
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
#define EPFNOSUPPORT 96 /* Protocol family not supported */
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
#define EADDRINUSE 98 /* Address already in use */
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
#define ENETDOWN 100 /* Network is down */
#define ENETUNREACH 101 /* Network is unreachable */
#define ENETRESET 102 /* Network dropped connection because of reset */
#define ECONNABORTED 103 /* Software caused connection abort */
#define ECONNRESET 104 /* Connection reset by peer */
#define ENOBUFS 105 /* No buffer space available */
#define EISCONN 106 /* Transport endpoint is already connected */
#define ENOTCONN 107 /* Transport endpoint is not connected */
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
#define ETIMEDOUT 110 /* Connection timed out */
#define ECONNREFUSED 111 /* Connection refused */
#define EHOSTDOWN 112 /* Host is down */
#define EHOSTUNREACH 113 /* No route to host */
#define EALREADY 114 /* Operation already in progress */
#define EINPROGRESS 115 /* Operation now in progress */
#define ESTALE 116 /* Stale NFS file handle */
#define EUCLEAN 117 /* Structure needs cleaning */
#define ENOTNAM 118 /* Not a XENIX named type file */
#define ENAVAIL 119 /* No XENIX semaphores available */
#define EISNAM 120 /* Is a named type file */
#define EREMOTEIO 121 /* Remote I/O error */
#define EDQUOT 122 /* Quota exceeded */
#define ENOMEDIUM 123 /* No medium found */
#define EMEDIUMTYPE 124 /* Wrong medium type */
#define ECANCELED 125 /* Operation Cancelled */
#define ENOKEY 126 /* Required key not available */
#define EKEYEXPIRED 127 /* Key has expired */
#define EKEYREVOKED 128 /* Key has been revoked */
#define EKEYREJECTED 129 /* Key was rejected by service */
#endif
许多GNU
C库中的函数都监测和报告错误的情况,而且有时候你的程序需要检查它们以得到错误的情形。比如说:你打开了一个输入文件,你必须检查这个文件是否正确的打开了,而且在你调用一个库函数出错的时候打印出错信息或采取其他的措施。
这一章描述错误报告功能是怎么工作的。要使用这个功能的话,你的程序必须包含头文件“errno.h”。
错误的检查
许多库函数返回一个特殊的值说明他们的失败。这个特殊值典型的有-1、一个空指针、或者一个定义得像EOF这样的常量。但是这样的返回只是告诉你错误发生了。要找到这是什么样的错误,你必须查看变量errno中存放的错误代码。这个变量在头文件“errno.h”中定义。
变量: volatile int errno
变量errno包括了系统的错误号,你可以改变它的值。
当errno描述成volatile,它将可能被一个信号处理者同步的改变;参见《定义信号处理者》。一个写好的信号处理者能够存入或恢复errno的值,所以处理你编写信号处理者的时候之外一般你基本不用担心这个。
程序器启动的似乎errno的初始值是零。许多库函数在遭遇一些确定的错误以后将保证设置它为某个确定的非零值。当这些函数运行成功的时候它将不会修改 errno的值;因此,当一个成功的调用以后errno的值不必要是零,而且你不能用errno来判断一次调用是否失败了。正确的做法是检查每个函数报道的结果,如果调用失败了,再来检查errno。
一些库函数会把errno设置为一个非零值来作为调用一个其他的可能出错的库函数的返回结果。你必须假定任何库函数都可能改变errno。
兼容性提示:ANSI
C把errno指定为一个比变量强的“可变左值”,允许它像宏一样实现。比如说:它可以扩展得包括一个函数调用:就像*
_errno()。实际上,那就是它自己在GNU系统上的本质。在非GNU系统上的GNU库中,就算不论怎样也是这样的。
这里有一些库函数,就像sqrt和atan,在万一出错的时候也能返回一个合法的值。对于这样的函数,如果你要检查是否发生了错误,推荐的手段就是在调用函数之前将errno设置为0,然后函数返回以后再检查它的值。
所有的错误代码都有一个符号名字;它们都是在“errno.h”中定义的宏。这些名字都由一个“E”开始后面跟着一个大写字母或数字;你必须把这些名字考虑成保留字,参见《保留字》
所有的错误代码都是互不相同的正整数。(比如:既然这些值是不同的,你就可以把它们用作switch结构的标签。)你不能对这些有特定值的符号常量假定其他的值。
errno的值并不仅限于这些宏,所以有些库函数在其他情形下会返回一些其他的错误码。当然手册列出的这些特定的库函数的这些特定的值是有另外的含义的
在非GNU的系统中,将一个无效的指针作为参数许多系统调用将返回EFAULT。
显然这结果会在在你的程序有bug的时候发生,而且该情况不会在GNU系统中发生,为节省篇幅,我们就不在进行单独的函数的描述的时候提及EFAULT。
错误代码
所有的错误代码都在头文见“errno.h”中定义,它们所有的展开以后都是整数常量。这里的有些错误在GNU的系统中不会发生,但是在其他系统中使用GNU库的时候会出现。
宏: int EPERM
操作不被允许;只有文件(或其他资源)或进程的主人才能有特权作这个操作。
宏: int ENOENT
没有这样的文件或目录。这是一个普通文件上的“文件不存在”错误,文件不在提到的目录表中。
宏: int ESRCH
没有进程符合指定的进程号。
宏: int EINTR
函数调用中断;一个异步信号出现而且阻止调用的执行。当出现这样的情况时,你必须试着重新调用。
你可以选择一个函数来在处理完信号以后恢复,这样比出现RINTR的失败要好,《简单的信号中断》。
宏: int EIO
输入输出错误;通常是物理的读写错。
宏: int ENXIO
没有这样的设备或地址。通常,这意味着一个文件描述的设备并没有正确安装,系统不能为它找到正确的设备驱动程序。
宏: int E2BIG
参数列表太长;当使用exec函数中的某一个执行新程序时传递的参数占用了太多的内存空间。这种情况不会出现在GNU的系统中。
宏: int ENOEXEC
无效的可执行文件格式。这种情况由exec函数检测出来;《执行一个文件》
宏: int EBADF
错误的文件描述符;比如说,在一个已经关闭的文件描述符上作IO操作或读取一个写打开的描述符(反之亦然)。
宏: int ECHILD
没有子进程。这个错误出现在想要作操纵子进程的操作的时候,已经没有任何可以操纵的子进程了。
宏: int EDEADLK
死锁避免;分配系统资源的时候将可能导致死锁的情况,比如说,参见《文件锁定》
宏: int ENOMEM
没有可用的内存。系统不能分配更多的虚拟内存因为它的容量已经满了。
宏: int EACCES
许可权被封锁;文件的许可权不允许所尝试的操作。
宏: int EFAULT
错误地址;检测到一个无效指针。
宏: int ENOTBLK
给出的这种方式需要块特殊文件而这个文件不是。比如说:试图把一个普通文件当文件系统挂在unix系统中将出现这个错误。
宏: int EBUSY
资源忙;一个正在使用的系统资源不能被共享。比如说,你需要删除的文件是一个挂在系统中的文件系统,你将得到这个错误。
宏: int EEXIST
文件已存在;应该对新文件操作的时候这个文件已经明确存在于目录表中。
宏: int EXDEV
尝试跨文件系统作文件链接。
宏: int ENODEV
在需要进去日指明设备类别的函数中给出了错误的设备类型。
宏: int ENOTDIR
在只能处理目录的时候给出的是文件而不是目录。
宏: int EISDIR
是一个目录文件;尝试打开一个目录文件来作写操作时就会发生这个错误。
宏: int EINVAL
无效的参数。用来指出传递给库函数参数时候的各种问题。
宏: int ENFILE
整个系统中打开了太多不同的文件。注意许多连结通道都会被计算成一个打开的文件;参见《连结通道》
宏: int EMFILE
当前进程已经打开了太多文件而且不能再打开了。
宏: int ENOTTY
不适当的IO控制操作,比如说在一个普通文件上试图设置终端模式。
宏: int ETXTBSY
一个打算运行的文件当前正被写打开,或要写打开的文件当前正在运行。(这个名字象征着“文本文件忙”。)在GNU的系统中这不是一个错误;可能的情况下文本文件将被复制。
宏: int EFBIG
文件太大。文件的大小超过了系统的允许。
宏: int ENOSPC
设备上没有空间;因为磁盘满而造成写操作失败。
宏: int ESPIPE
错误的查找操作(比如在管道中)。
宏: int EROFS
在一个只读的文件系统中试图修改一个文件。
宏: int EMLINK
太多的连接;单个文件的连结数太大。
宏: int EPIPE
断掉的管道;在管道的另一边没有进程来读取。所有库函数在返回这个错误代码的时候都会产生一个SIGPIPE信号;如果不处理或阻止的话这个信号将终止程序。如此,要是不处理或阻止SIGPIPE的话你的程序实际上看不到EPIPE。
宏: int EDOM
域错误;当数学函数得到的参数值不在函数允许范围内的时候出现这个错误。
宏: int ERANGE
范围错误;当数学函数的结果因上溢或下溢而无法描述的时候出现此错误。
宏: int EAGAIN
资源零是不可用;如果你稍候在作此调用或许会成功。只有fork会因为这个原因返回EAGAIN错误码。
宏: int EWOULDBLOCK
在一个非块格式的目标上作需要块的操作。
兼容性提示:在4.4BSD和GNU中,EWOULDBLOCK和EAGAIN是一样的。早期版本的BSD(参见《伯克利UNIX》)使用两个不同的代码,用EWOULDBLOCK来表示需要块的操作,而EAGAIN表示其他种类的错误。
宏: int EINPROGRESS
在一个选择为非块型的目标上的初始化操作不能立即完成。
宏: int EALREADY
在一个选择为非块型的目标上的一个操作正在进行。
宏: int ENOTSOCK
当需要一个套接字的时候指定的文件不是套接字。
宏: int EDESTADDRREQ
在套接字操作中没有指定目标地址。
宏: int EMSGSIZE
送往套接字的消息的大小操作的支持的最大尺寸。
宏: int EPROTOTYPE
所要求的通信协议不支持套接字的种类。
宏: int ENOPROTOOPT
你指定的套接字操作不能被使用的套接字的协议所识别,参见《套接字操作》
宏: int EPROTONOSUPPORT
套接字域不支持请求的通信协议。参见《创建一个套接字》
宏: int ESOCKTNOSUPPORT
套接字类型不被支持。
宏: int EOPNOTSUPP
你请求的操作不被支持。一些套接字函数不被所有类型的套接字识别,而且有些不能在所有的通信协议上实现。
宏: int EPFNOSUPPORT
你请求的套接字协议组不被支持。
宏: int EAFNOSUPPORT
一个套接字指定的地址组不被支持;它和套接字使用的协议不一致。参见《套接字》
宏: int EADDRINUSE
请求的套接字地址正在使用。参见《套接字地址》
宏: int EADDRNOTAVAIL
请求的套接字地址已经不可用;比如说,你试着把一个和本机名字不一样的名字给套接字。参见《套接字地址》
宏: int ENETDOWN
由于网络不通造成一个套接字操作失败。
宏: int ENETUNREACH
由于子网上的远程主机不可到达造成一个套接字操作失败。
宏: int ENETRESET
由于远程主机崩溃导致网络连接复位。
宏: int ECONNABORTED
一个网络连接被本地中断。
宏: int ECONNRESET
由于外界控制本地主机的原因造成一个网络连接关闭。比如远程的重启动。
宏: int ENOBUFS
IO操作的内核缓冲区都在使用。
宏: int EISCONN
你试图连接一个已经连接了的套接字。参见《创建一个连接》。
宏: int ENOTCONN
套接字没有连接任何东西。你得到这个错误的原因是你试图通过一个套接字传送数据,但是却没有先指定数据的目标。
宏: int ESHUTDOWN
套接字已经被关闭。
宏: int ETIMEDOUT
套接字操作在指定的超时时间间隔内没有收到回音。
宏: int ECONNREFUSED
远程主机拒绝建立网络连接。(通常是因为它并不运行请求的这种服务)
宏: int ELOOP
在查找文件名的时候遇到了许多指向它的符号连接。这个通常用来指出一个符号连接的环路。
宏: int ENAMETOOLONG
文件名太长(比PATH_MAX还要长;参见《文件系统容量限制》)货主机名字太长(在gethostname或sethostname中;参见《主机身份》
宏: int EHOSTDOWN
请求网络连接的远程主机停机。
宏: int EHOSTUNREACH
请求网络连接的远程主机不可到达。
宏: int ENOTEMPTY
在需要空目录的时候目录非空。通常这个错误出现在你准备删除一个目录的时候。
宏: int EUSERS
文件配额系统由于太多用户而拒绝。
宏: int EDQUOT
用户的磁盘限额已经超过。
宏: int ESTALE
过期的NFS文件句柄。这里只是了NFS系统的内部混乱而且需要对服务器主机的文件系统重新整理。修理这种问题通常需要在本地主机上卸下再重新挂上此NFS文件系统。
宏: int EREMOTE
一个使用文件名来通过NFS加载远程文件系统的时候此文件名已经指定给一个加载好的文件了。(这只是在某些操作系统上的错误,但是我们希望在GNU系统上能运行正常,使这个错误代码不可能实现)
宏: int ENOLCK
没有可用的锁定。由文件锁定功能使用;参见《文件锁》
宏: int ENOSYS
功能没有实现。一些功能包括命令和选项的定义可能没有被所有的实现所支持,也就是你请求这些没有被支持的功能的时候你会得到这一类的错误。
宏: int ED
有经验的用户将知道错误是什么。
宏: int EGRATUITOUS
这个错误信息没有用处。
错误信息
库里的函数和变量都设计得使你的程序在调用库失败的时候容易的使用自定义的错误信息报告格式。函数strerror和perror将按给定的错误代码给你标准的错误信息;变量program_invocation_short_name将使你在遇到错误的时候方便的访问你的程序名。
函数: char * strerror (int errnum)
strerr函数映射由参数errnum表示的错误代码(参见《检查错误》)到错误信息字符串。返回值是一个字符串指针。
通常errnum的值从变量errno中来。
你不能修改strerroe返回的字符串。同样,如果你后来又调用了strerror,这个字符串将会被覆盖。但是这里可以保证在你之后没有任何库函数调用strerror。
这个函数在“string.h”中声明。
函数 void perror (const char *message)
此函数将错误信息打印到流stderr。查看节《标准流》
如果你调用perroe的message不是一个空指针就是一个空字符串,perror将把这个消息打印到相应的errno中,在后面增加一个空行。
如果你提供一个非空的message参数,prror将把这个字符串作为它的输出的前缀。它将增加一个冒号和空格字符来分开message中对应errno的错误字符串。
函数perror在stdio.h中描述。
sterror和perror对给定的错误代码提供严格一致的信息,就是系统下都一致的准确文本。在GNU系统中,这个信息是相当短的;这里没有多行的信息或内嵌的新行。每个信息都由一个大写字母开始而且没有结束的标点符号。
兼容性提示:函数strerror是ANSI的新定义,许多老的C系统仍然不支持这个函数。
许多不从终端读取输入的程序都设计成如果系统调用错误就退出。而且约定,这样一个程序产生的错误信息都由这个程序的名字开始,没有目录名。你可以从变量 program_invocation_short_name中找到这个名字;完整的文件名存放在变量program_invocation_name 中。
变量: char * program_invocation_name
这个变量的值是用来调用产生当前进程的程序的名字。它和argv[0]一样。
变量: char * program_invocation_short_name
这个变量的值是用来调用产生当前进程的程序的名字,但是去掉了目录名。(就是说,这即便是program_invocation_name,也是减掉了一大半的。)
program_invocation_name和program_invocation_short_name都是系统在调用main之前设定的。
兼容性提示:这两个变量都是GNU的扩展,如果你想让你的程序能在非GNU的函数库上工作,你必须在main中存下argv[0]的值,并且你自己去掉目录名。我们增加这个扩展的目的是使写不需要外面的main协助的子程序也能自己进行错误报告。
这里有一个例子显示如如何恰当的处理打开一个文件的错误。函数open_sesame尝试打开一个指定名字的文件并且在成功的情况下返回一个流。库函数fopen在因为某些原因打不开一个文件的时候返回一个空指针。在这样的情形下,open_message使用strerror函数构造一个错误信息,然后终止程序。如果我们想在调用其他库函数的时候忽略strerror的错误代码,我们必须把原来的error
code为一个本地的内部变量,因为其他库函数可能会在其间覆盖errno。
#include
#include
#include
#include
FILE *
open_sesame (char *name)
{
FILE *stream;
errno = 0;
stream = fopen (name, "r");
if (!stream) {
fprintf (stderr, "%s: Couldn't open file %s; %s\n",
program_invocation_short_name, name, strerror (errno));
exit (EXIT_FAILURE);
} else
return stream;
}
阅读(1474) | 评论(1) | 转发(0) |