1 彙編編譯時不定義的內容
該文件的第一個內容是對宏__ASSEMBLY__的判斷,這個宏的作用是避免在進行彙編編譯的時候,不定義後續相關內容。這個宏通過在編譯器中用-D選項中加入,參數AFLAGS也包含該宏定義。在彙編時編譯器會定義__ASSEMBLY__爲1。
#ifndef __ASSEMBLY__
1.1 Sparse工具檢測使用的屬性定義
接下來是__CHECKER__宏的判斷,__CHECKER__宏在通過Sparse(Semantic Parser for C)工具對內核代碼進行檢查時會定義的。在使用make C=1或C=2時便會調用該工具,這個工具可以檢查在代碼中聲明瞭sparse所能檢查到的相關屬性的內核函數和變量。
#ifdef __CHECKER__
下面分析一下sparse所能檢查的相關屬性。
# define __user __attribute__((noderef, address_space(1)))
# define __kernel /* default address space */
# define __safe __attribute__((safe))
# define __force __attribute__((force))
# define __nocast __attribute__((nocast))
# define __iomem __attribute__((noderef, address_space(2)))
# define __acquires(x) __attribute__((context(x,0,1)))
# define __releases(x) __attribute__((context(x,1,0)))
# define __acquire(x) __context__(x,1)
# define __release(x) __context__(x,-1)
# define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0)
extern void __chk_user_ptr(const volatile void __user *);
extern void __chk_io_ptr(const volatile void __iomem *);
__user特性用來修飾一個變量的地址,該變量必須是非解除參考(no dereference)即地址是有效的,並且變量所在的地址空間必須爲1,這裏爲(address_space(1)),用戶地址空間。sparse把地址空間分爲3部分,0表示普通地址空間,對內核來說就是地址空間。1表示用戶地址空間。2表示設備地址映射空間,即設備寄存器的地址空間。
__kernel特性修飾變量爲內核地址,爲內核代碼裏面默認的地址空間。
__safe特性聲明該變量爲安全變量,這是爲了避免在內核函數未對傳入的參數進行校驗就使用的情況下,會導致編譯器對其報錯或輸出告警信息。 通過該特性說明該變量不可能爲空。
__force特性聲明該變量是可以強制類型轉換的。
__nocast聲明該變量參數類型與實際參數類型要一致纔可以。
__iomem聲明地址空間是設備地址映射空間,其他的與__user一樣。
__acquires爲函數屬性定義的修飾,表示函數內,該參數的引用計數值從1變爲0。
__releases與__acquires相反,這一對修飾符用於Sparse在靜態代碼檢測時,檢查調用的次數和匹配請求,經常用於檢測lock的獲取和釋放。
__acquire表示增加變量x的計數,增加量爲1。
__release表示減少變量x的計數,減少量爲1。這一對與上面的那一對是一樣,只是這一對用在函數的執行過程中,都用於檢查代碼中出現不平衡的狀況。
__cond_lock用於表示條件鎖,當c這個值不爲0時,計數值加1,並返回1。
__chk_user_ptr和__chk_io_ptr在這裏只聲明函數,沒有函數體,目的就是在編譯過程中Sparse能夠捕捉到編譯錯誤,檢查參數的類型。
轉載時請註明出處和作者聯繫方式
作者聯繫方式:張天才 [email protected]