在C编程中,errno是个不可缺少的变量,特别是在网络编程中。如果你没有用过errno,那只能说明你的程序不够健壮。当然,如果你是WIN32平台的GetLastError(),效果也是一样的。
为什么会使用errno呢?个人认为,这是系统库设计中的一个无奈之举,他更多的是个技巧,而不是架构上的需要。我们观察下函数结构,可以发现,函数的参数返回值只有一个,这个返回值一般可以携带错误信息,比如负数表示错误,而正数表述正确的返回值,比如recv函数。但是对于一些返回指针的函数,如:char *get_str();这个方法显然没有用的。NULL可以表示发生错误,但是发生什么错误却毫无办法。于是,errno就诞生了。全局变量errno可以存放错误原因,当错误发生时,函数的返回值是可以通过非法值来提示错误的发生。
二、errno的线程安全
errno是全局变量,但是在多线程环境下,就会变得很恐怖。当你调用一个函数时,发现这个函数发生了错误,但当你使用错误原因时,他却变成了另外一个线程的错误提示。想想就会觉得是件可怕的事情。
将errno设置为线程局部变量是个不错的主意,事实上,GCC中就是这么干的。他保证了线程之间的错误原因不会互相串改,当你在一个线程中串行执行一系列过程,那么得到的errno仍然是正确的。
看下,bits/errno.h的定义:
# ifndef __ASSEMBLER__
/* Function to get address of global `errno' variable. */
extern int *__errno_location (void) __THROW __attribute__ ((__const__));
# if !defined _LIBC || defined _LIBC_REENTRANT
/* When using threads, errno is a per-thread value. */
# define errno (*__errno_location ())
# endif
# endif /* !__ASSEMBLER__ */
而errno.h中是这样定义的:
/* Declare the `errno' variable, unless it's defined as a macro by
bits/errno.h. This is the case in GNU, where it is a per-thread
variable. This redeclaration using the macro still works, but it
will be a function declaration without a prototype and may trigger
a -Wstrict-prototypes warning. */
#ifndef errno
extern int errno;
#endif
显然,errno实际上,并不是我们通常认为的是个整型数值,而是通过整型指针来获取值
的。这个整型就是线程安全的。
三、errno的实现
staticpthread_key_t key;
static pthread_once_t key_once =PTHREAD_ONCE_INIT;
static void make_key()
{
(void)pthread_key_create(&key, NULL);
}
int *_errno()
{
int*ptr ;
(void) pthread_once(&key_once, make_key);
if((ptr = pthread_getspecific(key)) == NULL)
{
ptr =malloc(sizeof(int));
(void) pthread_setspecific(key,ptr);
}
return ptr ;
}
四、errno的应用
errno在库中得到广泛的应用,但是,错误编码实际上不止那么多。我们需要在自己的系统中增加更多的错误编码。一种方式就是直接利用errno,另外一种方式就是定义自己的user_errno。
使用errno,strerror可能无法解析,这需要自己解决。但errno使用线程变量的方式值得借鉴。
errno.h errno.h- -
查看错误代码errno是调试程序的一个重要方法。当linucC api函数发生异常时,一般会将errno变量(需includeerrno.h)赋一个整数值,不同的值表示不同的含义,可以通过查看该值推测出错的原因。在实际编程中用这一招解决了不少原本看来莫名其妙的问题。比较麻烦的是每次都要去linux源代码里面查找错误代码的含义,现在把它贴出来,以后需要查时就来这里看了。
以下来自linux2.4.20-18的内核代码中的/usr/include/asm/errno.h
#ifndef_I386_ERRNO_H
#define _I386_ERRNO_H
#define EPERM 1/* Operation not permitted */
#define ENOENT 2 /* Nosuch file or directory */
#define ESRCH 3 /* No suchprocess */
#defineEINTR 4 /* Interrupted system call */
#defineEIO 5 /* I/O error */
#defineENXIO 6 /* No such device or address */
#defineE2BIG 7 /* Arg list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad filenumber */
#define ECHILD 10 /* No child processes */
#defineEAGAIN 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 */
#defineEEXIST 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 */
#defineEINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File tableoverflow */
#define EMFILE 24 /* Too many open files */
#defineENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text filebusy */
#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 EMLINK31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#defineEDOM 33 /* Math argument out of domain of func */
#define ERANGE34 /* Math result not representable */
#define EDEADLK 35 /*Resource deadlock would occur */
#define ENAMETOOLONG 36 /* Filename too long */
#define ENOLCK 37 /* No record locks available*/
#define ENOSYS 38 /* Function not implemented */
#defineENOTEMPTY 39 /* Directory not empty */
#define ELOOP 40 /* Toomany symbolic links encountered */
#define EWOULDBLOCK EAGAIN /*Operation would block */
#define ENOMSG 42 /* No message ofdesired type */
#define EIDRM 43 /* Identifier removed */
#defineECHRNG 44 /* Channel number out of range */
#define EL2NSYNC 45 /*Level 2 not synchronized */
#define EL3HLT 46 /* Level 3 halted */
#defineEL3RST 47 /* Level 3 reset */
#define ELNRNG 48 /* Link number outof range */
#define EUNATCH 49 /* Protocol driver not attached*/
#define ENOCSI 50 /* No CSI structure available */
#defineEL2HLT 51 /* Level 2 halted */
#define EBADE 52 /* Invalidexchange */
#define EBADR 53 /* Invalid request descriptor*/
#define EXFULL 54 /* Exchange full */
#define ENOANO 55 /*No anode */
#define EBADRQC 56 /* Invalid request code */
#defineEBADSLT 57 /* Invalid slot */
#define EDEADLOCK EDEADLK
#defineEBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Devicenot a stream */
#define ENODATA 61 /* No data available */
#defineETIME 62 /* Timer expired */
#define ENOSR 63 /* Out of streamsresources */
#define ENONET 64 /* Machine is not on the network*/
#define ENOPKG 65 /* Package not installed */
#defineEREMOTE 66 /* Object is remote */
#define ENOLINK 67 /* Link hasbeen severed */
#define EADV 68 /* Advertise error */
#defineESRMNT 69 /* Srmount error */
#define ECOMM 70 /* Communicationerror on send */
#define EPROTO 71 /* Protocol error */
#defineEMULTIHOP 72 /* Multihop attempted */
#define EDOTDOT 73 /* RFSspecific 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 */
#defineEBADFD 77 /* File descriptor in bad state */
#define EREMCHG 78 /*Remote address changed */
#define ELIBACC 79 /* Can not access aneeded shared library */
#define ELIBBAD 80 /* Accessing acorrupted shared library */
#define ELIBSCN 81 /* .lib section ina.out corrupted */
#define ELIBMAX 82 /* Attempting to link in toomany shared libraries */
#define ELIBEXEC 83 /* Cannot exec ashared library directly */
#define EILSEQ 84 /* Illegal bytesequence */
#define ERESTART 85 /* Interrupted system call shouldbe 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 */
#defineEMSGSIZE 90 /* Message too long */
#define EPROTOTYPE 91 /*Protocol wrong type for socket */
#define ENOPROTOOPT 92 /*Protocol not available */
#define EPROTONOSUPPORT 93 /* Protocolnot supported */
#define ESOCKTNOSUPPORT 94 /* Socket type notsupported */
#define EOPNOTSUPP 95 /* Operation not supported ontransport endpoint */
#define EPFNOSUPPORT 96 /* Protocol familynot supported */
#define EAFNOSUPPORT 97 /* Address family notsupported by protocol */
#define EADDRINUSE 98 /* Address alreadyin use */
#define EADDRNOTAVAIL 99 /* Cannot assign requestedaddress */
#define ENETDOWN 100 /* Network is down */
#defineENETUNREACH 101 /* Network is unreachable */
#define ENETRESET 102/* Network dropped connection because of reset */
#defineECONNABORTED 103 /* Software caused connection abort */
#defineECONNRESET 104 /* Connection reset by peer */
#define ENOBUFS 105/* No buffer space available */
#define EISCONN 106 /* Transportendpoint is already connected */
#define ENOTCONN 107 /* Transportendpoint is not connected */
#define ESHUTDOWN 108 /* Cannot sendafter transport endpoint shutdown */
#define ETOOMANYREFS 109 /*Too many references: cannot splice */
#define ETIMEDOUT 110 /*Connection timed out */
#define ECONNREFUSED 111 /* Connectionrefused */
#define EHOSTDOWN 112 /* Host is down */
#defineEHOSTUNREACH 113 /* No route to host */
#define EALREADY 114 /*Operation already in progress */
#define EINPROGRESS 115 /*Operation now in progress */
#define ESTALE 116 /* Stale NFS filehandle */
#define EUCLEAN 117 /* Structure needs cleaning*/
#define ENOTNAM 118 /* Not a XENIX named type file */
#defineENAVAIL 119 /* No XENIX semaphores available */
#define EISNAM 120/* Is a named type file */
#define EREMOTEIO 121 /* Remote I/Oerror */
#define EDQUOT 122 /* Quota exceeded */
#defineENOMEDIUM 123 /* No medium found */
#define EMEDIUMTYPE 124 /*Wrong medium type */
#endif
来源:百度文库http://wenku.baidu.com/view/1cd8db29915f804d2b16c119.html
errno是一个全局整型变量,用于保存线程安全的错误代码。本文详细介绍了errno的实现方式,包括其线程安全的存储以及如何通过pthread_key_t进行管理。同时,讨论了errno在库中的应用,指出在自定义错误编码时可以考虑直接利用errno或创建user_errno。此外,列举了Linux系统中的常见错误代码及其含义,帮助开发者理解和排查问题。

1万+

被折叠的 条评论
为什么被折叠?



