许多的内核函数需要返回一个指针,但是函数的调用可能失败,一般我们处理这样的情形都是返回一个NULL指针,就像malloc或kmalloc在没有获得指定的空间申请时的返回值一样。但是有时我们想知道导致函数失败的原因,但是返回NULL就显得信息不够。因此有些函数返回一个实际的错误编码以便对引起错误的原因做一些处理。很多内核接口通过把错误值编码到一个指针值中来返回错误信息。
当处理这样的函数时,判断是否成功调用就不能是简单的和NULL进行比较。为了方便使用这样的类型接口,2.6的内核在linux/err.h中实现了三个内联函数:
/* * Kernel pointers have redundant information, so we can use a * scheme where we can return either an error code or a dentry * pointer with the same return value. * * This should be a per-architecture thing, to allow different * error and pointer decisions. */ #define IS_ERR_VALUE(x) unlikely((x) > (unsigned long)-1000L)
static inline void *ERR_PTR(long error) { return (void *) error; }
static inline long PTR_ERR(const void *ptr) { return (long) ptr; }
static inline long IS_ERR(const void *ptr) { return IS_ERR_VALUE((unsigned long)ptr); }
|
所幸的是,内核返回的指针一般是指向页面的边界(4K边界),即
ptr & 0xfff == 0
这样ptr的值不可能落在(0xfffff000,0xffffffff)之间,
而一般内核的出错代码也是一个小负数,在-1000到0之间,转变成unsigned long,
正好在(0xfffff000,0xffffffff)之间。因此可以用
(unsigned long)ptr > (unsigned long)-1000L
来判断内核函数的返回值是一个有效的指针,还是一个出错代码。
阅读(754) | 评论(0) | 转发(0) |