Linux中的errno
前言
Linux system call
是kernel
入口,通常不会被直接调用,而是由对应的C函数库包装来完成一些必要的步骤(trapping to kernel mode),同时也使用调用方式与普通库没有什么区别。
一般C包装函数功能如下:
- 将参数与
system call
代号copy到kernel
指定的寄存器 - trapping to kernel mode(开始执行)
- 返回
user mode
时,如果返回为error number
,则设置errno
C函数库也可以会为参数作预处理和返回值的后期处理。
man 2 syscalls
可以查看所有的系统调用。
返回值
当出现错误时,大部分system call
都会返回一个负值(如 error(3)
中定义的三个负值之一),C包装库函数会向调用者隐藏此细节:返回-1并将errno
的绝对值copy保存。
成功的system call
一般返回0,但也有返回非0值,具体查看对应的manual page.
某些情况下,开发者必须定义一个feature test macro
来从头文件(在manual page的SYNOPSYS
段中指定)中获取system call
的声明,该定义必须在include
任何头文件之前。此种情况下,macro
在manual中描述。更多关于feature test macro
的说明,可以参见 man 7 feature_test_macro
。
关于一些衍生UNIX
术语与及相关缩写的说明,可以参阅man 7 standards
。
直接调用
一般情况下无需直接调用system call
,但是有时并无C函数库对其进行妥善的封装,此时可以使用syscall(2)
来直接调用,历史上,也可以使用宏_syscall(2)
。
相关函数
errno
定义在<errno.h>
文件中,对支持多线程的系统,应为每个线程保存一个errno的copy,以避免相互干涉,因此在linux中,其定义是这样的。
errno定义成为函数的返回值(int型指针)所指向的值。
需要注意的是errno在没有新的错误产生时不会清零,所以请只在系统调用返回错误时检查它。errno也不会被设置为0, 0也没有对应的错误定义。
|
|
输入errno返回对应的说明。
直接打印输入”msg: “+errno对应的说明,比如msg可以是当前命令。
例程如下:
输出如下:
错误恢复
error
分为fatal
和nonfatal
, 对于fatal error
,能做的就是打印错误并退出程序;而非fatal
的错误,多半是与资源有关的 ,如EAGAIN
,ENFILE
,ENOBUFS
,ENOLCK
等,可以实施一些等待+重试操作来提升可靠性,避免不必要的退出。比如说检测到网络连接断开时,可以设定为等待一段时间后再次连接。有的程序使用指数算法,重试次数越多,等待时间显著增长。