學習撰寫 linux driver 往往使用 printk 當作第一個範例
printk(KERN_INFO "Hello, world n");
printk 主要的功能是將資料或訊息輸出到 kernel log buffer 中, “使用起來"很像 userspace 的 printf 函式.
比較特別的是 printk 本身有 “log level" 的概念, 適用於不同的情況, 本身定義在 include/linux/kern_levels.h 裡
關於 printk 的相關操作可在網路上找到豐富的資訊 [1] [2] [3]. 除此之外, 最底下的 reference 中也有許多詳細的介紹, 這邊就不多加敘述.
這一篇主要想講的是使用時機.
√ pr_*
pr_* 的函式定義在 include/linux/kern_levels.h 裡, 包含以下:
如上圖可知, pr_* 為封裝 printk 的巨集函式, 可讓使用者較方便且直覺的使用並維護輸出函式
這邊要注意的是 pr_cont, 由於 printk 函式會自動換行, 如果想在同一行繼續輸出, 則需要呼叫此函式. Linus 在這 [6]跟這 [8]有解釋原因.
√ dev_*
dev_* 的函式定義在 drivers/base/core.c 裡, 包含以下:
如上圖可知, 和 pr_* 函式不同的地方為 dev_* 函式第一個參數為 struct device 指標, 以 PCIe device driver 為例
使用時機:
- Device driver 中的輸出根據 log level 使用 dev_* 相關函式
- 其他則適情況使用對應的 pr_* 函式
- 避免直接呼叫 printk
- 適情況呼叫 pr_*_once 函式, 只輸出一次
- 多使用 ftrace [13] 來進行除錯, 而不是濫用 printk, pr_* or dev_*
詳細對應可見下表:
若使用 pr_debug, dev_dbg, 需透過下列方法打開 DEBUG 參數選項
1. Kernel config 選項
2. 在 Makefile 中加入 CFLAGS_[filename].o := -DDEBUG
若使用 dev_vdbg, 可透過下列方法打開 DEBUG 參數選項
1. Kernel config option
2. 在 Makefile 中加入 CFLAGS_[filename].o += -DVERBOSE_DEBUG
另可參考 [5] 第13章 Printing kernel messages. 除此之外, printk 還有許多衍生應用, 建議可以閱讀這篇好文 [7]
從 userspace 存取 kernel log buffer
可在 userspace 下透過 /dev/kmsg 介面來存取 kernel log buffer, 詳情可見 Documentation/ABI/testing/dev-kmsg
心得:
在不同場景選用適合的 pr_* 或者 dev_* 函式, 避免直接呼叫 printk.
此外, 也盡量使用 ftrace 來進行除錯以及問題定位.
References:
[1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/printk-formats.txt?id=HEAD
[2]: http://elinux.org/Debugging_by_printing
[3]: https://en.wikipedia.org/wiki/Printk
[4]: https://training.ti.com/sites/default/files/docs/Kernel-Debug-Series-Part3-printk.pdf
[5]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/coding-style.rst?id=HEAD
[6]: https://lwn.net/Articles/487437/
[7]: http://nairobi-embedded.org/printing_kernel_messages.html
[8]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4bcc595ccd80decb4245096e3d1258989c50ed41
[9]: http://blog.rongpmcu.com/printk/
[10]: https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1480716.html
[11]: https://plus.google.com/+DavidMiller/posts/KaRo6LaVCx5
[12]: http://blog.csdn.net/guodongping/article/details/9822935
[13]: https://www.kernel.org/doc/Documentation/trace/ftrace.txt