現在的位置: 首頁 > 綜合 > 正文

linux/err.h

2018年04月17日 ⁄ 綜合 ⁄ 共 2111字 ⁄ 字型大小 評論關閉

<linux/err.h>文件的代碼

#ifndef _LINUX_ERR_H
#define _LINUX_ERR_H

#include <linux/compiler.h>

#include <asm/errno.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 MAX_ERRNO    4095

#ifndef __ASSEMBLY__

#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)

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);
}

/**

 * ERR_CAST - Explicitly cast an error-valued pointer to another pointer type

 * @ptr: The pointer to cast.

 *

 * Explicitly cast an error-valued pointer to another pointer type in such a

 * way as to make it clear that's what's going on.

 */

static inline void *ERR_CAST(const void *ptr)
{

    /* cast away the const */

    return (void *) ptr;
}

#endif

#endif /* _LINUX_ERR_H */



內核函數返回一個指針給調用者,而這些函數中很多可能會失敗。在大部分情況下,失敗是通過一個NULL指針值來表示的,所以只要將返回指針和NULL進行比較,就可以知道函數調用是否成功,如kmalloc。這種方法雖然用起來方便,但它有個缺點:無法知道函數調用失敗的原因。因此,許多內核介面通過錯誤值編碼(怎麼編碼呢?後面講)到一個指針值來返回錯誤信息。我們可以得用err.h中的函數,來獲取導致函數調用失敗的原因。

我們首先來看下錯誤值是怎麼編碼的。
http://apps.hi.baidu.com/share/detail/19833514
http://linux.chinaunix.net/bbs/thread-1019406-1-1.html

我們知道,一般的內核出錯代碼是一個小負數,在-1000和0之間(最大的也在-MAX_ERRNO,0,其中MAX_ERRNO在err.h中定義,剛好在2的12次方之內)。

我們還知道,負數是以補碼的方式存儲在計算機中的,故-4095在內存中的十六進位為:0xfffff000。
內核返回的指針一般是指向頁面的邊界(4K邊界),即ptr && 0xfff == 0

也就是說,ptr的值不可能落在(0xfffff000, 0xffffffff)之間。所以,如果返回的指針值在上述區間之間,則應該是返回的錯誤值的補碼。
因此,可以根據一個指針指針值是否大於-MAX_ERRNO,即0xfffff000,來判斷這個指針值是否是錯誤的,自然也就知道這個函數調用是否成功。

#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)

再來分別看下幾個內聯函數

static inline void *ERR_PTR(long error)
{

    return (void *) error;
}

它是將有符號的錯誤碼轉換成指針。


static inline long PTR_ERR(const void *ptr)
{

    return (long) ptr;
}

它是將錯誤碼指針轉換成錯誤碼,因為一個錯誤指針的值在(0xfffff000, 0xffffffff)之間,錯誤碼的補碼也在這個區間之間,故只需要強制轉換一下即可。


static inline long IS_ERR(const void *ptr)
{

    return IS_ERR_VALUE((unsigned long)ptr);
}

這個函數的意思是顯而易見的。

注意下使用問題:應該先使用IS_ERR對一個指針進行判斷,在其返回真,也是就確實是一個錯誤指針時,才用PTR_ERR函數進行把錯誤編碼提取出來。

抱歉!評論已關閉.