Linux 系统错误码 errno 剖析 admin 2023-09-18 11:09:02 篇首语:本文由小编为大家整理,主要介绍了Linux 系统错误码 errno 剖析相关的知识,希望对你有一定的参考价值。 一、errno 介绍1.1 errno 简介Linux 中系统调用的错误都存储于错误码 errno 中。errno 由操作系统维护,存储就近发生的错误,即下一次的错误码会覆盖掉上一次的错误。errno 是一个包含在 中的预定义的外部 int 变量,用于表示最近一个函数调用是否产生了错误。若为0,则无错误;其它值均表示某一种错误。代码中需要包含 #include ,当一个系统调用或着库函数的调用失败时,将会重置错误码 errno。用户在判断程序出错后,立即检验 errno 的值可以获取错误码和错误信息。1.2 errno是线程安全的在 Linux 上,全局 errno 变量是特定于线程的。POSIX 要求 errno 必须是线程安全的。参阅:Thread-safety and POSIX.1 (unix.org)在 POSIX.1 中,errno 被定义为外部全局变量。但是此定义在多线程环境中是不可接受的,因为使用它会导致不确定的结果。问题是两个或多个线程可能会遇到错误,所有错误都会导致设置相同的错误号。在这种情况下,一个线程可能已经被另一个线程更新后,最终检查 errno。为了避免产生不确定性,POSIX.1c 将 errno 重新定义为可以访问每个线程错误号的服务:某些函数可能在通过符号 errno 访问的变量中提供错误号。errno 符号是通过包括 C 标准所指定的标头来定义的。对于进程的每个线程,errno 的值不应受函数调用或其他线程对 errno 的分配的影响。参阅:errno(3): number of last error - Linux man page (die.net)errno 是线程本地的;在一个线程中设置它不会影响在其他任何线程中的值我们可以通过在机器上运行一个简单的程序来进行检查。#include #include #include #define NTHREADS 5void *thread_function(void *dummyPtr) printf("Thread number %ld addr(errno):%p\n", pthread_self(), &errno);int main() pthread_t thread_id[NTHREADS]; int i, j; for (i = 0; i < NTHREADS; i++) pthread_create(&thread_id[i], NULL, thread_function, NULL); for (j = 0; j < NTHREADS; j++) pthread_join(thread_id[j], NULL); return 0;输出结果:1.3 errno 宏定义在头文件「/usr/include/asm-generic/errno-base.h」中对基础的常用 errno 进行了宏定义:defineerrnoexplainEPERM1Operation not permittedENOENT2No such file or directoryESRCH3No such processEINTR4Interrupted system callEIO5I/O errorENXIO6No such device or addressE2BIG7Argument list too longENOEXEC8Exec format errorEBADF9Bad file numberECHILD10No child processesEAGAIN11Try againENOMEM12Out of memoryEACCES13Permission deniedEFAULT14Bad addressENOTBLK15Block device requiredEBUSY16Device or resource busyEEXIST17File existsEXDEV18Cross-device linkENODEV19No such deviceENOTDIR20Not a directoryEISDIR21Is a directoryEINVAL22Invalid argumentENFILE23File table overflowEMFILE24Too many open filesENOTTY25Not a typewriterETXTBSY26Text file busyEFBIG27File too largeENOSPC28No space left on deviceESPIPE29Illegal seekEROFS30Read-only file systemEMLINK31Too many linksEPIPE32Broken pipeEDOM33Math argument out of domain of funcERANGE34Math result not representable在 「/usr/include/asm-generic/errno.h」 中,对剩余的 errno 做了宏定义:defineerrnoexplainEDEADLK35Resource deadlock would occurENAMETOOLONG36File name too longENOLCK37No record locks availableENOSYS38Function not implementedENOTEMPTY39Directory not emptyELOOP40Too many symbolic links encounteredEWOULDBLOCKEAGAINOperation would blockENOMSG42No message of desired typeEIDRM43Identifier removedECHRNG44Channel number out of rangeEL2NSYNC45Level 2 not synchronizedEL3HLT46Level 3 haltedEL3RST47Level 3 resetELNRNG48Link number out of rangeEUNATCH49Protocol driver not attachedENOCSI50No CSI structure availableEL2HLT51Level 2 haltedEBADE52Invalid exchangeEBADR53Invalid request descriptorEXFULL54Exchange fullENOANO55No anodeEBADRQC56Invalid request codeEBADSLT57Invalid slotEDEADLOCKEDEADLKEBFONT59Bad font file formatENOSTR60Device not a streamENODATA61No data availableETIME62Timer expiredENOSR63Out of streams resourcesENONET64Machine is not on the networkENOPKG65Package not installedEREMOTE66Object is remoteENOLINK67Link has been severedEADV68Advertise errorESRMNT69Srmount errorECOMM70Communication error on sendEPROTO71Protocol errorEMULTIHOP72Multihop attemptedEDOTDOT73RFS specific errorEBADMSG74Not a data messageEOVERFLOW75Value too large for defined data typeENOTUNIQ76Name not unique on networkEBADFD77File descriptor in bad stateEREMCHG78Remote address changedELIBACC79Can not access a needed shared libraryELIBBAD80Accessing a corrupted shared libraryELIBSCN81.lib section in a.out corruptedELIBMAX82Attempting to link in too many shared librariesELIBEXEC83Cannot exec a shared library directlyEILSEQ84Illegal byte sequenceERESTART85Interrupted system call should be restartedESTRPIPE86Streams pipe errorEUSERS87Too many usersENOTSOCK88Socket operation on non-socketEDESTADDRREQ89Destination address requiredEMSGSIZE90Message too longEPROTOTYPE91Protocol wrong type for socketENOPROTOOPT92Protocol not availableEPROTONOSUPPORT93Protocol not supportedESOCKTNOSUPPORT94Socket type not supportedEOPNOTSUPP95Operation not supported on transport endpointEPFNOSUPPORT96Protocol family not supportedEAFNOSUPPORT97Address family not supported by protocolEADDRINUSE98Address already in useEADDRNOTAVAIL99Cannot assign requested addressENETDOWN100Network is downENETUNREACH101Network is unreachableENETRESET102Network dropped connection because of resetECONNABORTED103Software caused connection abortECONNRESET104Connection reset by peerENOBUFS105No buffer space availableEISCONN106Transport endpoint is already connectedENOTCONN107Transport endpoint is not connectedESHUTDOWN108Cannot send after transport endpoint shutdownETOOMANYREFS109Too many references: cannot spliceETIMEDOUT110Connection timed outECONNREFUSED111Connection refusedEHOSTDOWN112Host is downEHOSTUNREACH113No route to hostEALREADY114Operation already in progressEINPROGRESS115Operation now in progressESTALE116Stale file handleEUCLEAN117Structure needs cleaningENOTNAM118Not a XENIX named type fileENAVAIL119No XENIX semaphores availableEISNAM120Is a named type fileEREMOTEIO121Remote I/O errorEDQUOT122Quota exceededENOMEDIUM123No medium foundEMEDIUMTYPE124Wrong medium typeECANCELED125Operation CanceledENOKEY126Required key not availableEKEYEXPIRED127Key has expiredEKEYREVOKED128Key has been revokedEKEYREJECTED129Key was rejected by serviceEOWNERDEAD130Owner diedENOTRECOVERABLE131State not recoverableERFKILL132Operation not possible due to RF-killEHWPOISON133Memory page has hardware error二、打印 errno若想要打印 errno,需要包含头文件 #include 。2.1 使用 perror 打印错误信息函数原型:void perror(const char *s)头 文 件:#include 作 用:打印系统错误信息2.2 使用 strerror 显示错误信息函数原型:char *strerror(int errnum);头 文 件:#include 作 用:将错误码以字符串的信息显示出来三、输出 errno 的小 Demo#include #include static void __Process(char *str) if (strstr(str, "_ASM_GENERIC_") != NULL || strstr(str, "define") == NULL) return; if (strstr(str, "EWOULDBLOCK") != NULL || strstr(str, "EDEADLOCK") != NULL) return; char szDefine[64] = 0; int errno = -1; char szExplain[64] = 0; sscanf(str, "%*[^A-Z]%s%*[^0-9]%d %*[^*]* %[^*]s", szDefine, &errno, szExplain); szExplain[strlen(szExplain) - 1] = 0; // 去除最后的空格 char buf[1024] = 0; snprintf(buf, sizeof(buf), "|%s|%d|%s|", szDefine, errno, szExplain); puts(buf);int main() freopen("/usr/include/asm-generic/errno-base.h", "r", stdin); // 读文件 // freopen("E:\\Documents\\stdin&&stdout\\stdout\\文件名", "w", stdout); // 写文件 while (1) char str[1024] = 0; fgets(str, sizeof(str), stdin); if (0 == strncmp(str, "#endif", 6)) break; __Process(str); puts("-----------------------------------------------------------"); freopen("/usr/include/asm-generic/errno.h", "r", stdin); // 读文件 while (1) char str[1024] = 0; fgets(str, sizeof(str), stdin); if (0 == strncmp(str, "#endif", 6)) break; __Process(str); 参考资料Linux errno详解 - Jimmy_Nie - 博客园 (cnblogs.com)errno 介绍_shanandqiu的博客-CSDN博客sscanf函数使用详解_faihung的博客-CSDN博客fgets函数及其用法,C语言fgets函数详解_发狂的蜗牛的博客-CSDN博客linxu中系统错误码errnoUnix errno值、 只要一个Unix函数(如,某个套接字函数)中有错误发生,全局变量errno就被设置为一个指明该错误类型的正直,函数本身则通过返回-1. errno的值只在函数发生错误时被设置,如果函数不返回错误,errno的值就没有定义。 errno的所有证书错误值都是常值,具有以“E”开头的全大写字母名字,并通常在头文件中定义,0值不表示任何错误; sys_errlist#include #include #include #include #include #include int main(int argc, char **argv){ int sockfd = 0; if ((sockfd = socket(0, SOCK_STREAM, 0)) < 0) { if (errno >= 0 && errno <= sys_nerr) printf("socket created, failed[%d], reason:%s", errno, sys_errlist[errno]); printf("%s",strerror(errno)); //头文件string.h内 } else { printf("socket successful"); } return 0;}输出结果:socket created, failed[97], reason:Address family not supported by protocolAddress family not supported by protocol 以上是关于Linux 系统错误码 errno 剖析的主要内容,如果未能解决你的问题,请参考以下文章 CAD中如何标注圆弧的长度? sqlserver删除语句 sqlserver删除语句条件 您可能还会对下面的文章感兴趣: 相关文章 浏览器打不开网址提示“ERR_CONNECTION_TIMED_OUT”错误代码的解决方法 如何安装ocx控件 VMware的虚拟机为啥ip地址老是自动变化 vbyone和EDP区别 linux/debian到底怎么重启和关机 苹果平板键盘被弄到上方去了,如何调回正常? 机器学习常用距离度量 如何查看kindle型号