Sparse¶
Sparse 是 C 程式的語義檢查器;它可用於查詢核心程式碼中一些潛在的問題。請參閱https://lwn.net/Articles/689907/ 以獲取 sparse 的概述;本文件包含一些核心特定的 sparse 資訊。 有關 sparse 的更多資訊,主要關於其內部結構,可以在其官方頁面 https://sparse.docs.kernel.org 中找到。
使用 sparse 進行型別檢查¶
“__bitwise” 是一個型別屬性,所以你必須這樣做
typedef int __bitwise pm_request_t;
enum pm_request {
PM_SUSPEND = (__force pm_request_t) 1,
PM_RESUME = (__force pm_request_t) 2
};
這使得 PM_SUSPEND 和 PM_RESUME 成為“bitwise”整數(“__force” 在這裡是因為 sparse 會抱怨在 bitwise 型別之間進行轉換,但在這種情況下我們確實 _想_ 強制轉換)。並且因為列舉值都是相同的型別,所以現在 “enum pm_request” 也將是該型別。
對於 gcc,所有的 “__bitwise”/“__force stuff” 都消失了,並且對於 gcc 來說,所有這些最終看起來都像整數。
坦率地說,你不需要那裡的列舉。 以上所有內容實際上都歸結為一種特殊的 “int __bitwise” 型別。
所以更簡單的方法就是這樣做
typedef int __bitwise pm_request_t;
#define PM_SUSPEND ((__force pm_request_t) 1)
#define PM_RESUME ((__force pm_request_t) 2)
現在你已經擁有了嚴格型別檢查所需的所有基礎設施。
一個小提示:常數整數“0”很特別。 你可以使用常數零作為按位整數型別,而 sparse 永遠不會抱怨。 這是因為 “bitwise”(顧名思義)旨在確保按位型別不會混淆(小端與大端與 cpu 端與任何東西),並且常量 “0” 確實 _是_ 特殊的。
使用 sparse 進行鎖檢查¶
以下宏對於 gcc 是未定義的,並在 sparse 執行時定義,以使用 sparse 的“上下文”跟蹤功能,應用於鎖機制。 這些註釋告訴 sparse 何時持有鎖,關於帶註釋的函式的入口和出口。
__must_hold - 在函式入口和出口時持有指定的鎖。
__acquires - 在函數出口時持有指定的鎖,但在入口時未持有。
__releases - 在函式入口時持有指定的鎖,但在出口時未持有。
如果函式進入和退出時都沒有持有鎖,則以平衡的方式在函式內部獲取和釋放鎖,則不需要任何註釋。 上述三個註釋用於 sparse 會報告上下文不平衡的情況。
獲取 sparse¶
你可以從以下位置獲取最新發布版本的 tarball:https://kernel.linux.club.tw/pub/software/devel/sparse/dist/
或者,你可以使用 git 克隆來獲取 sparse 最新開發版本的快照
git://git.kernel.org/pub/scm/devel/sparse/sparse.git
一旦你有了它,只需做
make
make install
作為普通使用者,它會將 sparse 安裝到你的 ~/bin 目錄中。
使用 sparse¶
使用 “make C=1” 進行核心 make,以便在所有重新編譯的 C 檔案上執行 sparse,或者使用 “make C=2” 在檔案上執行 sparse,無論它們是否需要重新編譯。 如果你已經構建了整個樹,這是檢查整個樹的快速方法。
可選的 make 變數 CF 可用於將引數傳遞給 sparse。 構建系統自動將 -Wbitwise 傳遞給 sparse。
請注意,sparse 定義了 __CHECKER__ 預處理器符號。