1. 程式人生 > >Linux核心除錯printk()總結

Linux核心除錯printk()總結

我們在使用printk()函式中使用日誌級別為的是使程式設計人員在程式設計過程中自定義地進行資訊的輸出,更加容易地掌握系統當前的狀況。
對程式的除錯起到了很重要的作用。
(下文中的日誌級別和控制檯日誌控制級別是一個意思)


printk(日誌級別 "訊息文字");這裡的日誌級別通俗的說指的是對文字資訊的一種輸出範圍上的指定。
日誌級別一共有8個級別,printk的日誌級別定義如下(在linux26/includelinux/kernel.h中):
#defineKERN_EMERG"<0>"/*緊急事件訊息,系統崩潰之前提示,表示系統不可用*/
#defineKERN_ALERT"<1>"/*報告訊息,表示必須立即採取措施*/
#defineKERN_CRIT"<2>"/*臨界條件,通常涉及嚴重的硬體或軟體操作失敗*/
#defineKERN_ERR"<3>"/*錯誤條件,驅動程式常用KERN_ERR來報告硬體的錯誤*/
#defineKERN_WARNING"<4>"/*警告條件,對可能出現問題的情況進行警告*/
#defineKERN_NOTICE"<5>"/*正常但又重要的條件,用於提醒。常用於與安全相關的訊息*/
#defineKERN_INFO"<6>"/*提示資訊,如驅動程式啟動時,列印硬體資訊*/
#defineKERN_DEBUG"<7>"/*除錯級別的訊息*/


沒有指定日誌級別的printk語句預設採用的級別是 DEFAULT_ MESSAGE_LOGLEVEL(這個預設級別一般為<4>,即與KERN_WARNING在一個級別上),其定義在linux26/kernel/printk.c中可以找到。
下面是一個比較簡單的使用
printk(KERN_INFO "INFO\n");  //這裡可以使用數字代替 KERN_INFO,即可以寫成printk(<6> "INFO\n");  
在這個格式的定義中,日誌級別和資訊文字之間不能夠使用逗號隔開,因為系統在進行編譯的時候,將日誌級別轉換成字串於後面的文字資訊進行連線。


在對系統輸出進行控制時,主要是討論控制檯和偽終端的輸情況,以及系統日誌等。


下面是控制檯日誌級別的一些簡要的介紹
控制檯相應的日誌級別定義如下:
#define MINIMUM_CONSOLE_LOGLEVEL  1   /*可以使用的最小日誌級別*/
#define DEFAULT_CONSOLE_LOGLEVEL  7 /*比KERN_DEBUG 更重要的訊息都被列印*/


int console_printk[4] = {
DEFAULT_CONSOLE_LOGLEVEL,/*控制檯日誌級別,優先順序高於該值的訊息將在控制檯顯示*/
/*預設訊息日誌級別,printk沒定義優先順序時,列印這個優先順序以上的訊息*/
DEFAULT_MESSAGE_LOGLEVEL,
/*最小控制檯日誌級別,控制檯日誌級別可被設定的最小值(最高優先順序)*/
MINIMUM_CONSOLE_LOGLEVEL,
DEFAULT_CONSOLE_LOGLEVEL,/* 預設的控制檯日誌級別*/
};
在進行檢視的時候,可以使用命令 cat /proc/sys/kernel/printk來檢視這四個值
可以通過修改檔案/proc/sys/kernel/printk中的第一個值來更改當前的控制檯日誌級別。


(宣告:在下面的模組函式中控制檯所使用的日誌級別均為KERN_WARNING級別)當日志級別高於console_loglevel(控制檯日誌級別)時,訊息才能在控制檯顯示出來。
假如我們寫了一個如下的模組函式:
1 #include <linux/init.h>
2 #include <linux/module.h>
3 MODULE_LICENSE("Dual BSD/GPL");
4 static int book_init(void)
5 {
6   printk(KERN_EMERG "EMERG\n");
7   printk(KERN_ALERT "ALERT\n");
8   printk(KERN_CRIT " CRIT\n");
9   printk(KERN_ERR " ERR\n");
10  printk(KERN_WARNING ""WARNING\n");
11   printk(KERN_NOTICE "NOTICE\n");
12  printk(KERN_INFO "INFO\n");
13  printk(KERN_DEBUG "DEBUG\n");
14  return 0;
    }
15static void book_exit(void)
16{
17  printk(KERN_ALERT "Book module exit\n");
    }
18  module_init(book_init);
19  module_exit(book_exit);


在控制檯(這裡指的是虛擬終端  Ctrl+Alt+(F1~F6))載入模組以後,控制檯給出的資訊為
6~9行中要求輸出的資訊,我們在偽終端(如果對偽終端不是很清楚可以看相關的內容)上執行命令tail -n 10 /var/log/messages檢視日誌檔案剛才得到的執行記錄
可以發現messages中的值為KERN_WARNING級別之後所要求輸出到資訊值。而如果我們在檔案syslog和kern-log中檢視系統日誌檔案,一般情況下可以得到所有的輸出資訊


Jul 18 11:44:19 xiyoulinux-desktop kernel: [16100.637057] INFO
Jul 18 11:44:19 xiyoulinux-desktop kernel: [16100.637063] CRIT
Jul 18 11:44:19 xiyoulinux-desktop kernel: [16100.637066] WARNING
Jul 18 11:44:19 xiyoulinux-desktop kernel: [16100.637068] ERR
Jul 18 11:44:19 xiyoulinux-desktop kernel: [16100.637069] ALERT
Jul 18 11:44:19 xiyoulinux-desktop kernel: [16100.637070] EMERG
Jul 18 11:44:19 xiyoulinux-desktop kernel: [16100.637071]  NOTICE 
Jul 18 11:44:19 xiyoulinux-desktop kernel: [16100.637072] DEBUG
(不過在有些機器上執行得到的結果並不是這樣的)
即一般情況下,syslog和kern.log兩個檔案中記錄的內容從程式設計這個角度來看是基本一致的。
在目錄/var/log/下有一下四個檔案可以檢視日誌
syslog ,kern.log,messages ,DEBUG 。   
syslog和kern.log一般情況下可以得到所有的系統輸出值,而messages得到的是比控制檯日誌級別低的輸出值,DEBUG得到的僅僅是DEBUG級別的
輸出值。
一般情況下,優先順序高於控制檯日誌級別的訊息將被列印到控制檯。優先順序低於控制檯日誌級別的訊息將被列印到messages日誌檔案中,而在偽終端下不列印任何的資訊。
我們在進行有關程式設計的時候,若使用到printk()這個函式,一般檢視資訊是在messages和虛擬終端下進行檢視,而對於syslog和kern.log下是用來檢驗所有資訊的輸出情況。