ERR_PTR PTR_ERR IS_ERR ERROR
在linux-x.xx/include/uapi/asm-generic/errno-base.h和errno.h里分别定义了返回错误的信息。
errno-base.h:
1 #ifndef _ASM_GENERIC_ERRNO_BASE_H 2 #define _ASM_GENERIC_ERRNO_BASE_H 3 4 #define EPERM 1 /* Operation not permitted */ 5 #define ENOENT 2 /* No such file or directory */ 6 #define ESRCH 3 /* No such process */ 7 ...... 8 ...... 9 ...... 10 #define EDOM 33 /* Math argument out of domain of func */ 11 #define ERANGE 34 /* Math result not representable */ 12 13 #endif
errno.h:
1 #define _ASM_GENERIC_ERRNO_H 2 3 #include <asm-generic/errno-base.h> 4 5 #define EDEADLK 35 /* Resource deadlock would occur */ 6 #define ENAMETOOLONG 36 /* File name too long */ 7 #define ENOLCK 37 /* No record locks available */ 8 ...... 9 ...... 10 ...... 11 #define ERFKILL 132 /* Operation not possible due to RF-kill */ 12 13 #define EHWPOISON 133 /* Memory page has hardware error */ 14 15 #endif
以上可知错误信息在1~133之间,返回错误会添加-号,故返回-133~-1。
部分函数内部有记录错误的信息并且返回。
对于返回非指针的函数,一般返回-ERROR。对于返回指针的函数,需要把ERROR转化为指针。
ERR_PTR、PTR_ERR和IS_ERR定义在linux-x.xx/include/linux/err.h:
1 #define MAX_ERRNO 4095 2 3 #ifndef __ASSEMBLY__ 4 EPERM 5 #define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO) 6 ERROR 7 static inline void * __must_check ERR_PTR(long error) //把错误转化指针 8 { 9 return (void *) error; 10 } 11 12 static inline long __must_check PTR_ERR(const void *ptr) //把指针转化错误 13 { 14 return (long) ptr; 15 } 16 17 static inline long __must_check IS_ERR(const void *ptr) //判断是否错误指针 18 { 19 return IS_ERR_VALUE((unsigned long)ptr); 20 } 21 22 static inline long __must_check IS_ERR_OR_NULL(const void *ptr) //判断空指针或者错误指针 23 { 24 return !ptr || IS_ERR_VALUE((unsigned long)ptr); 25 }
重点关注IS_ERR的实现。首先把指针转化成long,然后和(unsigned long)-4095比较。
对于32位系统,-4095=0xFFFF F001,对于64位系统,-4095=0xFFFF FFFF FFFF F001
对于32位系统,内核从0xFFFF F001 ~ 0xFFFF FFFF是冗余空间,对于64位系统,内核从0xFFFF FFFF FFFF F001 ~ 0xFFFF FFFF FFFF FFFF是冗余空间。
分配任何指针不可能到达这个区域,而错误信息在-133~-1在这个区域,故可判断系统的错误指针,从而判断返回的错误指针。