標籤:
轉自:http://blog.chinaunix.net/uid-20196318-id-28769.html
最近在使用filp_open開啟檔案時遇到到一個問題,當開啟一個並不存在的檔案時,filp_open傳回值值為0xfffffffe,而並不是0(NULL),這是因為核心對返回指標的函數做了特殊處理。核心中的函數常常返回指標,通常如果調用出錯,會返回NULLnull 指標,但linux做了更精妙的處理,能夠通過返回的指標體現出來。
對任何一個指標,必然有三種情況:一種是有效指標,一種是NULL,null 指標,一種是錯誤指標,或者說無效指標。而所謂的錯誤指標就是指其已經到達了最後一個page,比如對於32bit的系統來說,核心空間最高地址0xffffffff,那麼最後一個page就是指的0xfffff000~0xffffffff(以4K大小頁為例)。這段地址是被保留的,如果超過這個地址,則肯定是錯誤的。
在linux/err.h中包含了這一機制的處理,主要通過IS_ERR, PTR_ERR, ERR_PTR幾個宏。
/*
* 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 MAX_ERRNO 4095
#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)
/* 將錯誤號碼轉化為指標,由於錯誤號碼在-1000~0間,返回的指標會落在最後一頁 */
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);
}
所以對於核心中返回的指標,檢查錯誤的方式不是if(!retptr),而是if( IS_ERR(retptr) 或
If( IS_ERR_VALUE(retptr) )。
核心IS_ERR宏解析 【轉】