gqb666
1、最近在寫i2c下eeprom的驅動程式,但發現使用i2c_new_probed_device函式無法列舉到裝置,於是想除錯該函式(位於driver/i2c/i2c-core.c內),看到其中有些除錯資訊如下:
[cpp]view plain
copy
i2c_new_probed_device(...)
...
}
但載入驅動模組,該類除錯資訊並未列印出來(執行dmesg命令後同樣未找到除錯資訊)。
2、列出dev_dbg原始碼實現:(include/linux/device.h中)
[cpp]view plain
copy
#if defined(debug)
#define dev_dbg(dev, format, arg...) \
dev_printk(kern_debug , dev , format , ## arg)
問題找出,只需在引用標頭檔案#
include/linux/device.h前定義debug巨集即可。
在include/linux/i2c.h中修改**如下:
[cpp]view plain
copy
#define debug /* add for debug eeprom */
#include /* for struct device */
#undef debug /* add for debug eeprom */
載入驅動驅動模組後,並沒有除錯資訊列印出。如下圖:
但執行dmesg命令後
probing failed, no device found已經能夠列印出來,如下圖:
這是為什麼呢?
3、注意dev_printk的列印級別:
[cpp]view plain
copy
dev_printk(kern_debug , dev , format , ## arg)
這裡有個kern_debug的列印級別,其他級別如下(include/linux/kern_levels.h中):
#define kern_emerg kern_soh "0" /* system is unusable */
#define kern_alert kern_soh "1" /* action must be taken immediately */
#define kern_crit kern_soh "2" /* critical conditions */
#define kern_err kern_soh "3" /* error conditions */
#define kern_warning kern_soh "4" /* warning conditions */
#define kern_notice kern_soh "5" /* normal but significant condition */
#define kern_info kern_soh "6" /* informational */
#define kern_debug kern_soh "7" /* debug-level messages */
可以看到kern_debug級別最低為7。
再看/include/linux/printk.h下的乙個巨集:
[cpp]view plain
copy
#define console_loglevel_default 7 /* anything more serious than kern_debug */
該行表示只有列印級別高於default_console_loglevel(值小於default_console_loglevel的值)的列印才會出現在終端上。而 kern_debug也為7,所以我們的除錯不會直接列印出來。
將該行修改為:
[cpp]view plain
copy
#define console_loglevel_default 8 /* anything more serious than kern_debug */
來保證kern_debu的值小於default_console_loglevel,然後載入eeprom驅動模組後:除錯資訊能夠正確列印出來。
在核心中經常見到一些除錯列印資訊。pr_debug,pr_err等。以前的理解是以為只有出錯才會將pr_err中的內容列印出來,現在看來是錯的。pr_err並不等同與perror。
關於pr_err,pr_debug的定義有兩種:
第一種(tools\perf\util\debug.h)
int eprintf(int level,
const char *fmt, ...) __attribute__((format(printf, 2, 3)));
#define pr_err(fmt, ...) \
eprintf(0, pr_fmt(fmt), ##__va_args__)
#define pr_warning(fmt, ...) \
eprintf(0, pr_fmt(fmt), ##__va_args__)
#define pr_info(fmt, ...) \
eprintf(0, pr_fmt(fmt), ##__va_args__)
#define pr_debug(fmt, ...) \
eprintf(1, pr_fmt(fmt), ##__va_args__)
#define pr_debugn(n, fmt, ...) \
eprintf(n, pr_fmt(fmt), ##__va_args__)
#define pr_debug2(fmt, ...) pr_debugn(2, pr_fmt(fmt), ##__va_args__)
#define pr_debug3(fmt, ...) pr_debugn(3, pr_fmt(fmt), ##__va_args__)
#define pr_debug4(fmt, ...) pr_debugn(4, pr_fmt(fmt), ##__va_args__)
第二種(tools\virtio\linux\kernel.h)
#define pr_err(format, ...) fprintf (stderr, format, ## __va_args__)
#ifdef debug
#define pr_debug(format, ...) fprintf (stderr, format, ## __va_args__)
#else
#define pr_debug(format, ...) do {} while (0)
#endif
#define dev_err(dev, format, ...) fprintf (stderr, format, ## __va_args__)
#define dev_warn(dev, format, ...) fprintf (stderr, format, ## __va_args__)
第一種定義,可以看出pr_err,pr_debug,pr_warning,pr_info實質上都是一樣的,eprintf就是printf函式。__attribute__((format(printf, 2, 3)));表示printf格式化字串從printf的第2個引數開始,可變引數從printf的第3個引數開始。關於attribute的介紹可以參加這裡
所以,對於核心**中出現pr_err,pr_debug,pr_warning,pr_info都是列印資訊到終端。
第二種定義,關鍵是對fprintf的理解了。
fprintf(stderr, "can't open it!\n");fprintf(stdout, "can't open it!\n");
stdout -- 標準輸出裝置 (printf("..")) 同 stdout。也就是說兩者都是要向終端螢幕列印資訊的。stderr -- 標準錯誤輸出裝置
兩者預設向螢幕輸出。
但如果用轉向標準輸出到磁碟檔案,則可看出兩者區別。stdout輸出到磁碟檔案,stderr在螢幕。
【總結】:pr_err pr_debug等呼叫時,都會列印到終端螢幕的,不管之前的語句是否發生錯誤。之所以有幾種定義,是為了**清晰。
Linux驅動開發之DRM驅動
qq群 852283276 b站 主頁 drm 驅動程式開發 開篇 drm 驅動程式開發 vkms 最簡單的drm應用程式 single buffer drm 驅動是如何建立 fb device 的 linux中的drm 介紹 linux graphic dri 顯示子系統 介紹1 xilinx d...
linux驅動開發之demo
linux版本 uname r 2.6.18 1.2798.fc6 編譯 進入模組 所在目錄 make c usr src kernels 2.6.18 1.2798.fc6 m pwd modules 載入 insmod test.ko 檢視主裝置號 自動分配為no 253 dmesg 建立裝置 ...
linux裝置驅動之PCIE驅動開發
pcie pci express 是intel提出的新一代的匯流排介面,目前普及的pcie 3.0的傳輸速率為8gt s,下一代pcie 4.0將翻番為16gt s,因為傳輸速率快廣泛應用於資料中心 雲計算 人工智慧 機器學習 視覺計算 顯示卡 儲存和網路等領域。pcie插槽是可以向下相容的,比如p...