IS_ERR()有一些妙处。
内核中的函数常常返回指针,问题是如果出错,也希望能够通过返回的指针体现出来。
所幸的是,内核返回的指针一般是指向页面的边界(4K边界),即
ptr & 0xfff == 0
这样ptr的值不可能落在(0xfffff000,0xffffffff)之间,
而一般内核的出错代码也是一个小负数,在-1000到0之间,转变成unsigned long,
正好在(0xfffff000,0xffffffff)之间。因此可以用
(unsigned long)ptr > (unsigned long)-1000L
来判断内核函数的返回值是一个有效的指针,还是一个出错代码。
涉及到的任何一个指针,必然有三种情况,一种是有效指针,一种是NULL,空指针,一种是错误指针,或者说无效指针.而所谓的错误指针就是指其已经到达了最后一个page.比如对于32bit的系统来说,内核空间最高地址0xffffffff,那么最后一个page就是指的0xfffff000~0xffffffff(假设4k一个page).这段地址是被保留的,如果超过这个地址,则肯定是错误的。
Linux内核中,出错有多种可能:
include/asm-generic/errno-base.h文件:
#define EPERM
1
#define ENOENT
2
#define ESRCH
3
#define EINTR
4
#define EIO
5
#define ENXIO
6
#define E2BIG
7
#define ENOEXEC
8
#define EBADF
9
#define ECHILD
10
#define EAGAIN
11
#define ENOMEM
12
#define EACCES
13
#define EFAULT
14
#define ENOTBLK
15
#define EBUSY
16
#define EEXIST
17
#define EXDEV
18
#define ENODEV
19
#define ENOTDIR
20
#define EISDIR
21
#define EINVAL
22
#define ENFILE
23
#define EMFILE
24
#define ENOTTY
25
#define ETXTBSY
26
#define EFBIG
27
#define ENOSPC
28
#define ESPIPE
29
#define EROFS
30
#define EMLINK
31
#define EPIPE
32
#define EDOM
33
#define ERANGE
34
而出错时,往往返回的是-EBUSY,-EINVAL,-ENODEV,-EPIPE,-EAGAIN,-ENOMEM等等,可以看到,这个值实际上是在-1000~0之间的。
对于一个返回指针的函数,我们通常返回NULL表示失败,但是这不能指出那种失败(内存不足?硬件错误还是网络不可达?)
所以返回的时候用ERR_PTR(-ENOME) 等就可以判断,因为这个指针显然不合法
参考 include/iinux/err.h
所幸的是,内核返回的指针一般是指向页面的边界(4K边界),即
ptr & 0xfff == 0
这样ptr的值不可能落在(0xfffff000,0xffffffff)之间,
而一般内核的出错代码也是一个小负数,在-1000到0之间,转变成unsigned long,
正好在(0xfffff000,0xffffffff)之间。因此可以用
(unsigned long)ptr > (unsigned long)-1000L
来判断内核函数的返回值是一个有效的指针,还是一个出错代码。
涉及到的任何一个指针,必然有三种情况,一种是有效指针,一种是NULL,空指针,一种是错误指针,或者说无效指针.而所谓的错误指针就是指其已经到达了最后一个page.比如对于32bit的系统来说,内核空间最高地址0xffffffff,那么最后一个page就是指的0xfffff000~0xffffffff(假设4k一个page).这段地址是被保留的,如果超过这个地址,则肯定是错误的。
Linux内核中,出错有多种可能:
include/asm-generic/errno-base.h文件:
#define EPERM
#define ENOENT
#define ESRCH
#define EINTR
#define EIO
#define ENXIO
#define E2BIG
#define ENOEXEC
#define EBADF
#define ECHILD
#define EAGAIN
#define ENOMEM
#define EACCES
#define EFAULT
#define ENOTBLK
#define EBUSY
#define EEXIST
#define EXDEV
#define ENODEV
#define ENOTDIR
#define EISDIR
#define EINVAL
#define ENFILE
#define EMFILE
#define ENOTTY
#define ETXTBSY
#define EFBIG
#define ENOSPC
#define ESPIPE
#define EROFS
#define EMLINK
#define EPIPE
#define EDOM
#define ERANGE
而出错时,往往返回的是-EBUSY,-EINVAL,-ENODEV,-EPIPE,-EAGAIN,-ENOMEM等等,可以看到,这个值实际上是在-1000~0之间的。
对于一个返回指针的函数,我们通常返回NULL表示失败,但是这不能指出那种失败(内存不足?硬件错误还是网络不可达?)
所以返回的时候用ERR_PTR(-ENOME) 等就可以判断,因为这个指针显然不合法
参考 include/iinux/err.h