前言
本节来学习Linux错误码,因为内核中的函数常常返回指针,如果出错,也希望能够通过返回的指针体现出来。
嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程,未来预计四个月将高强度更新本专栏,喜欢的可以关注本博主并订阅本专栏,一起讨论一起学习。现在关注就是老粉啦!
内核返回的指针
在介绍之前,我们需要理解一下内核空间最大的错误码。对于一个64位的系统而言,内核空间占用(0x0000000000000000 ~ 0xffffffffffffffff)的虚拟地址。其中Linux采用分页机制管理内存,而CPU访问的是线性地址需要通过页表转化成物理地址。所以内核就约定留出最后一页4k(fffffffffffff000 ~ 0xffffffffffffffff)用来记录内核空间的错误指针。
因此所谓的错误指针已经指向了内核空间的最后一页
指针一般有三种:合法指针、错误指针、NULL指针。
合法指针:内核返回的指针一般是指向页面的边界,即ptr & 0xfff == 0
非法指针:不指向任何有效内存地址
错误指针:错误指针是指指向无效、未定义或未分配内存的指针
IS_ERR()
将传入的值与(unsigned long)-MAX_ERRNO
的值进行比较,在Linux中,定义了MAX_ERRNO
的定义为4095,其含义就是最大错误号。
-4096的二进制是补码,其值为0xfffff001,即大于等于0xfffff001的指针为非法指针。而这一部分正好是Linux内核的最后一页,存储的错误码,对应的值就是错误类型。
IS_ERR()
的结果:
有效指针、空指针返回false
错误指针返回true
IS_ERR_OR_NULL()
和IS_ERR()的区别在于其NULL也返回true
有效指针返回false
错误指针、空指针返回true
PTR_ERR()
将传入的void *类型指针强转为long类型,并返回。用于将错误指针转为long类型值,从而返回出错误类型
ERR_PTR()
将传入的long类型强转为void *类型指针,并返回
使用案例
imx6uirq.class = class_create(THIS_MODULE, IMX6UIRQ_NAME);
if (IS_ERR(imx6uirq.class)) {
return PTR_ERR(imx6uirq.class);
}
imx6uirq.device = device_create(imx6uirq.class, NULL, imx6uirq.devid, NULL, IMX6UIRQ_NAME);
if (IS_ERR(imx6uirq.device