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__ 預處理器符號。