使用 printk 進行訊息日誌記錄¶
printk() 是 Linux 核心中最廣為人知的函式之一。它是我們用於列印訊息的標準工具,通常也是追蹤和除錯最基本的方式。如果您熟悉 printf(3),就會知道 printk() 是基於它的,儘管它有一些功能上的差異
printk()訊息可以指定一個日誌級別。格式字串雖然大體上與 C99 相容,但並未遵循完全相同的規範。它有一些擴充套件和一些限制(沒有
%n或浮點轉換說明符)。請參閱 如何正確使用 printk 格式說明符。
所有 printk() 訊息都會列印到核心日誌緩衝區,這是一個透過 /dev/kmsg 匯出到使用者空間的環形緩衝區。通常使用 dmesg 來讀取它。
printk() 通常這樣使用:
printk(KERN_INFO "Message: %s\n", arg);
其中 KERN_INFO 是日誌級別(注意它與格式字串連線在一起,日誌級別不是單獨的引數)。可用的日誌級別有:
名稱 |
字串 |
別名函式 |
|---|---|---|
KERN_EMERG |
“0” |
|
KERN_ALERT |
“1” |
|
KERN_CRIT |
“2” |
|
KERN_ERR |
“3” |
|
KERN_WARNING |
“4” |
|
KERN_NOTICE |
“5” |
|
KERN_INFO |
“6” |
|
KERN_DEBUG |
“7” |
|
KERN_DEFAULT |
“” |
|
KERN_CONT |
“c” |
日誌級別指定了訊息的重要性。核心根據訊息的日誌級別和當前的 console_loglevel(一個核心變數)來決定是否立即顯示該訊息(將其列印到當前控制檯)。如果訊息優先順序高於(日誌級別值較低)console_loglevel,則訊息將被列印到控制檯。
如果省略日誌級別,訊息將以 KERN_DEFAULT 級別列印。
您可以使用以下命令檢查當前的 console_loglevel:
$ cat /proc/sys/kernel/printk
4 4 1 7
結果顯示了 current(當前)、default(預設)、minimum(最小)和 boot-time-default(啟動時預設)日誌級別。
要更改當前的 console_loglevel,只需將所需的級別寫入 /proc/sys/kernel/printk。例如,要將所有訊息列印到控制檯:
# echo 8 > /proc/sys/kernel/printk
另一種方法,使用 dmesg:
# dmesg -n 5
將 console_loglevel 設定為列印 KERN_WARNING (4) 或更嚴重的訊息到控制檯。更多資訊請參閱 dmesg(1)。
作為 printk() 的替代,您可以使用 pr_*() 別名進行日誌記錄。這組宏將日誌級別嵌入到宏名稱中。例如:
pr_info("Info message no. %d\n", msg_num);
列印一條 KERN_INFO 訊息。
除了比等效的 printk() 呼叫更簡潔之外,它們還可以透過 pr_fmt() 宏為格式字串使用一個通用定義。例如,在原始檔頂部(在任何 #include 指令之前)定義此內容:
#define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__
將會在該檔案中的每個 pr_*() 訊息前加上產生訊息的模組和函式名。
出於除錯目的,還有兩個條件編譯宏:pr_debug() 和 pr_devel(),除非定義了 DEBUG(或者在 pr_debug() 的情況下還定義了 CONFIG_DYNAMIC_DEBUG),否則它們不會被編譯。
函式參考¶
-
pr_fmt¶
pr_fmt (fmt)
由 pr_*() 宏用於生成 printk 格式字串
引數
fmt從 pr_*() 宏傳遞的格式字串
描述
此宏可用於為 pr_*() 宏生成統一的格式字串。常見的用途是在檔案中所有 pr_*() 訊息前加上一個通用字串。例如,在原始檔頂部定義此內容:
#define pr_fmt(fmt) KBUILD_MODNAME “: “ fmt
將會在檔案中所有 pr_info、pr_emerg 等訊息前加上模組名稱。
-
printk¶
printk (fmt, ...)
列印核心訊息
引數
fmt格式字串
...可變引數
描述
這是 printk()。它可以在任何上下文中呼叫。我們希望它能正常工作。
如果啟用了 printk 索引,則從 printk_index_wrap 呼叫 _printk()。否則,printk 只是 #定義為 _printk。
我們嘗試獲取 console_lock。如果成功,就很容易——我們記錄輸出並呼叫控制檯驅動程式。如果未能獲取訊號量,我們將輸出放入日誌緩衝區並返回。當前持有 console_sem 的程序將在 console_unlock() 中注意到新的輸出;並在釋放鎖之前將其傳送到控制檯。
這種延遲列印的一個影響是,呼叫 printk() 然後更改 console_loglevel 的程式碼可能會出現問題。這是因為 console_loglevel 是在實際列印時檢查的。
另請參閱:printf(3)
有關 C99 格式字串擴充套件的更多資訊,請參閱 vsnprintf() 文件。
-
pr_emerg¶
pr_emerg (fmt, ...)
列印緊急級別訊息
-
pr_alert¶
pr_alert (fmt, ...)
列印警報級別訊息
-
pr_crit¶
pr_crit (fmt, ...)
列印關鍵級別訊息
-
pr_err¶
pr_err (fmt, ...)
列印錯誤級別訊息
-
pr_warn¶
pr_warn (fmt, ...)
列印警告級別訊息
-
pr_notice¶
pr_notice (fmt, ...)
列印通知級別訊息
-
pr_info¶
pr_info (fmt, ...)
列印資訊級別訊息
-
pr_cont¶
pr_cont (fmt, ...)
在同一行繼續上一條日誌訊息。
引數
fmt格式字串
...格式字串的引數
描述
此宏擴充套件為具有 KERN_CONT 日誌級別的 printk。它只應用於在沒有換行符('n')的情況下繼續日誌訊息。否則,它將預設回退到 KERN_DEFAULT 日誌級別。
-
pr_devel¶
pr_devel (fmt, ...)
有條件地列印除錯級別訊息
引數
fmt格式字串
...格式字串的引數
描述
如果定義了 DEBUG,此宏將擴充套件為具有 KERN_DEBUG 日誌級別的 printk。否則,它不執行任何操作。
它使用 pr_fmt() 來生成格式字串。
-
pr_debug¶
pr_debug (fmt, ...)
有條件地列印除錯級別訊息