關於errno的後事妥善處理

在這裏插入圖片描述

前言

當UNIX函數出現錯誤時,常常返回一個負值,而且整型變量errno通常被設置爲含有附加信息的一個值。例如,open函數如果成功執行則返回一個非負文件描述符,如出錯則返回-1.在open出錯時,有大約15種不同的errno值(文件不存在、權限問題等)。某些函數並不返回負值而是使用另一種約定。例如,返回一個指向對象指針的大多數函數,在出錯時,將返回一個NULL指針。

文件==<errno.h>==中定義了符號errno以及可以賦予的各個常量,這些常量都以字符E開頭。例如,若errno等於常量EACESS,這表示產生了權限問題(例如,沒有打開所要求文件的足夠權限)。
POSIX和ISO C將errno定義爲這一一個符號,它擴展成爲一個可以修改的整型左值。這可以是包含出錯編號的一個整數,或是一個返回出錯編號指針的函數。以前使用的定義是:
extern int errno;

但是在支持線程的環境中,多個線程共享進程地址空間,每個線程都有屬於自己的局部errno以避免一個線程干擾另一個線程。

對於errno應當知道兩條規則。第一條規則:如果沒有出錯,則其值不會被一個例程清除。因此,僅當函數返回指明出錯時,才檢驗其值。第二條:任何一個函數都不會將errno值設置爲0,在<errno.h>中定義的所有常量都不爲0。

C標準定義了兩個函數,它們幫助打印出錯信息。

#include <string.h>
char *strerror(int errnum);

此函數將errnum(它通常就是errno值)映射到一個出錯信息字符串,並且返回此字符串的指針。

perror函數基於errno的當前值,在標準錯誤上產生一條出錯信息,

#include <stdio.h>
 
void perror(const char *msg);

它首先輸出由msg指向的字符串,然後是一個冒號,一個空格,接着是對應於errno值的出錯信息,最後是一個換行符。

出錯恢復
可與將<errno.h>中定義的各種出錯分出致命性的非致命性的兩類。對於致命性的錯誤,無法執行恢復動作,最多隻能在用戶屏幕上打印一條出錯信息,或者將一條出錯信息寫到日誌文件中,然後終止。關於這點可以看我的:段錯誤?打的就是段錯誤!
而對於非致命性錯誤,有課可以較爲妥善的處理。大多數非致命性錯誤在本質上是暫時的,例如資源短缺,當系統中活動較少時,這種出錯很可能就不會發生。

與資源相關的非致命性出錯包括EAGAIN. ENFILE、ENOBUFS、ENOLCK、ENOSPC、ENOSR、EWOULDBLOCK, 有時ENOMEM也是非致命性出錯。當EBUSY指明共享資源正在使用時,也可將它作爲非致命性出錯處理。當EINTR中斷- -慢速系統調用時,可將它作爲非致命性出錯處理。

對於資源相關的非致命性出錯,一般恢復動作是延遲一些時間, 然後再試。這種技術可應用於其他情況。例如,假設-個 出錯表明一個 網絡連接不再起作用, 那麼應用程序可以在短時間延遲後重建該連接。某些應用使用指數補償算法,在每次重複中等待更長時間。

最後,取決於應用程序的開發者,他可以決定那些出錯是可恢復的。如若使用一種從錯誤中恢復的合理策略,那麼由於避免了應用程序的異常終止,就能改善應用程序的健壯性。

栗子

對於中斷的read、write系 統調用,POSIX.I的語 義在該標準的2001版有所改變。對於如何處理已read、write部分數據量的相應系統調用,早期版本允許實現進行選擇。如若read系統調用已接收並傳送數據至應用程序緩衝區,但尚未接收到應用程序請求的全部數據,此時被中斷、操作系統可以認爲該系統調用失敗、並將errno設置爲EINTR;另一種處理方式是允許該系統調用成功返回,返回已接收到的部分數據量。與此類似,如若write巳傳輸了應用程序緩衝區中的部分數據,然後被中斷,操作系統可以認爲該系統調用失敗,並將ermo設置爲EINTR;另一種處理方式是允許該系統調用成功返回,返回已寫的部分數據量。歷史上,從系統V派生的實現,將這種系統調用視爲失敗,而BSD派生的實現則處理爲部分成功返回。POSIX.1 標準的2001版採用BSD風格的語義。

假定一個讀操作,它被中斷,我們要恢復它:

again:
if(n= read(fd, buf, BUFSIZE)) < 0)
	if (errno == EINTR)
		goto again;/* just an interrupted system call * /
/* handle other errors */

errno表

其實看不看這個表意義不大,但是有的人他就是想看,那我就貼一份吧。

查看系統中所有的errno所代表的含義,可以採用如下的代碼:

/* Function: obtain the errno string
*   char *strerror(int errno)
*/

#include <stdio.h>
#include <string.h>     //for strerror()
//#include <errno.h>
int main()
{
    int tmp = 0;
    for(tmp = 0; tmp <=256; tmp++)
    {
        printf("errno: %2d\t%s\n",tmp,strerror(tmp));
    }
    return 0;
}

輸出信息如下:

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
errno: 133      Memory page has hardware error
errno: 134~255  unknown error!

Linux中,在頭文件 /usr/include/asm-generic/errno-base.h 對基礎常用errno進行了宏定義:

#ifndef _ASM_GENERIC_ERRNO_BASE_H
#define _ASM_GENERIC_ERRNO_BASE_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  /* Argument 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 */

#endif/usr/include/asm-asm-generic/errno.h 中,對剩餘的errno做了宏定義:

#ifndef _ASM_GENERIC_ERRNO_H
#define _ASM_GENERIC_ERRNO_H

#include <asm-generic/errno-base.h>

#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 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 Canceled */
#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 */

/* for robust mutexes */
#define EOWNERDEAD  130 /* Owner died */
#define ENOTRECOVERABLE 131 /* State not recoverable */

#define ERFKILL     132 /* Operation not possible due to RF-kill */

#define EHWPOISON   133 /* Memory page has hardware error */

#endif
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章