亚洲综合图片区自拍_思思91精品国产综合在线观看_一区二区三区欧美_欧美黑人又粗又大_亚洲人成精品久久久久桥本

世界熱議:Linux內核學習筆記:printk調試

2023-06-01 15:09:52 來源:嵌入式Linux充電站

很多內核開發(fā)者喜歡的調試工具是printk,在Linux內核中,使用printk()函數(shù)來打印信息,它與C庫的printf()函數(shù)類似。

printk()與printf()的一個重要區(qū)別是: printk()提供輸出等級。內核會根據(jù)這個等級來判斷是否在終端或者串口中輸出。


【資料圖】

printk等級

路徑:include/linux/kern_levels.h

#define KERN_EMERG KERN_SOH "0"  /* 最高輸出等級,系統(tǒng)可能處于不可用的狀態(tài) */#define KERN_ALERT KERN_SOH "1"  /* 緊急和理科需要處理的輸出 */#define KERN_CRIT KERN_SOH "2"  /* 緊急情況 */#define KERN_ERR KERN_SOH "3"  /* 發(fā)生錯誤的情況 */#define KERN_WARNING KERN_SOH "4" /* 警告 */#define KERN_NOTICE KERN_SOH "5"  /* 重要的提示 */#define KERN_INFO KERN_SOH "6"  /* 提示信息 */#define KERN_DEBUG KERN_SOH "7"  /* 調試輸出 */

Linux內核為printk定義了8個輸出等級,KERN_EMERG等級最高,KERN_DEBUG等級最低。在配置內核時,由一個宏來設置系統(tǒng)默認的輸出等級CONFIG_MESSAGE_LOGLEVEL_DEFAULT,通常這個默認輸出等級為4,因此只有輸出等級高于4時才會輸出到終端或者串口,即只有KERN_EMERG~KERN_ERR滿足這個條件。

通常在產(chǎn)品開發(fā)階段,會把系統(tǒng)默認等級設置為最低,以便在開發(fā)測試階段可以暴露更多的問題和調試信息,在發(fā)布產(chǎn)品時再把輸出等級設置為0或者4。

修改printk等級

# cat /proc/sys/kernel/printk  //printk默認有4個等級7  4  1  7

四個數(shù)字分表代表:

控制臺輸出等級

默認消息等級

最低輸出等級

默認控制臺輸出等級

在系統(tǒng)運行時,我們也可以修改系統(tǒng)的輸出等級。打開所有的內核輸出:

echo 8 > /proc/sys/kernel/printk  //打開所有的內核輸出

另外,還可以通過在啟動內核時傳遞commandline給內核的方法來修改系統(tǒng)默認的輸出等級。例如,使用uboot引導內核時,可以在uboot傳參的bootargs參數(shù)上,加上“loglevel=8”,這樣在系統(tǒng)啟動時,就打開了所有內核輸出。

printk的輸出格式

在實際調試中,printk()可以和printf()一樣,直接輸出一條字符串。

不過為了更好的顯示一些調試信息,可以加上函數(shù)名字(__func__)和代碼行號(__LINE__),例如:

printk(KERN_EMERG"figo:%s, %d", __func__, __LINE__);

在雙引號""前加上輸出等級KERN_EMERG,代表輸出等級為0。

另外,在使用printk()的時候需要注意輸出格式,否則在編譯時會出現(xiàn)很多的警告。printk的輸出格式:

數(shù)據(jù)類型printk格式符
int%d或%x
unsigned int%u或%x
long%ld或%lx
long long%lld或%llx
unsigned long long%llu或%llx
size_t%zu或%zx
size_t%zd或%zx
函數(shù)指針%pf

pr_xx( )封裝

在使用printk的時候需要手動添加輸出等級KERN_INFO、KERN_WARNING等,這樣還是有些麻煩。因此,Linux內核也對printk進行了進一步的封裝。

Linux內核將每一個輸出等級封裝為pr_xx()函數(shù),例如,輸出等級KERN_INFO封裝為pr_info(),輸出等級KERN_WARNING封裝為pr_warn()。具體如下:

#define pr_emerg(fmt, ...) \\ printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)#define pr_alert(fmt, ...) \\ printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)#define pr_crit(fmt, ...) \\ printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)#define pr_err(fmt, ...) \\ printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)#define pr_warn(fmt, ...) \\ printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)#define pr_notice(fmt, ...) \\ printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)#define pr_info(fmt, ...) \\ printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)#define pr_err(fmt, ...) \\ printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)

這里對輸出等級為KERN_DEBUG的封裝是比較特殊的,因為debug等級比較常用,內核對pr_debug()分為了三種情況:

如果設置了 CONFIG_DYNAMIC_DEBUG,則此pr_debug()擴展為 dynamic_pr_debug(),主要用于 動態(tài)輸出。否則,如果定義了 DEBUG宏,則它等同于具有 KERN_DEBUG日志級別的 printk。 如果未定義 DEBUG,則它什么都不做。

pr_debug()的定義如下:

/* If you are writing a driver, please use dev_dbg instead*/#if defined(CONFIG_DYNAMIC_DEBUG) || \\ (defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))#include < linux/dynamic_debug.h >/** * pr_debug - Print a debug-level message conditionally * @fmt: format string * @...: arguments for the format string * * This macro expands to dynamic_pr_debug() if CONFIG_DYNAMIC_DEBUG is * set. Otherwise, if DEBUG is defined, it"s equivalent to a printk with * KERN_DEBUG loglevel. If DEBUG is not defined it does nothing. * * It uses pr_fmt() to generatethe format string (dynamic_pr_debug() uses * pr_fmt() internally). */#define pr_debug(fmt, ...)   \\ dynamic_pr_debug(fmt, ##__VA_ARGS__)#elif defined(DEBUG)#define pr_debug(fmt, ...) \\ printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)#else#define pr_debug(fmt, ...) \\ no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)#endif

標簽:

上一篇:訊息:Linux內核學習筆記:動態(tài)輸出調試
下一篇:最后一頁