Linux kernel

printk, pr_* and dev_* 使用時機

學習撰寫 linux driver 往往使用 printk 當作第一個範例

printk(KERN_INFO "Hello, world \n");

printk 主要的功能是將資料或訊息輸出到 kernel log buffer 中, “使用起來”很像 userspace 的 printf  函式.

比較特別的是 printk 本身有 “log level” 的概念, 適用於不同的情況, 本身定義在 include/linux/kern_levels.h 裡

圖片2.png

關於 printk 的相關操作可在網路上找到豐富的資訊 [1] [2] [3]. 除此之外, 最底下的 reference 中也有許多詳細的介紹,  這邊就不多加敘述.

這一篇主要想講的是使用時機.


√ pr_*

pr_* 的函式定義在 include/linux/kern_levels.h 裡, 包含以下:

2017-09-12_161742.png

如上圖可知, pr_* 為封裝 printk 的巨集函式, 可讓使用者較方便且直覺的使用並維護輸出函式

這邊要注意的是 pr_cont, 由於 printk 函式會自動換行, 如果想在同一行繼續輸出, 則需要呼叫此函式. Linus 在這 [6]跟這 [8]有解釋原因.


√ dev_*

dev_* 的函式定義在 drivers/base/core.c 裡, 包含以下:

2017-09-13_161947.png

如上圖可知, 和 pr_* 函式不同的地方為 dev_* 函式第一個參數為 struct device 指標, 以 PCIe device driver 為例

2017-09-13_165023.png


使用時機:

  • 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

發表迴響