Linux内核调试输出

老是忘记,遂总结如下

输出等级

一般在内核中,调试输出函数为printk,用法同printf,但是printk输出的信息具有日志级别,日志级别是通过在printk()输出的字符串前加一个带尖括号的整数来控制的,如printk("<6>Hello, world!/n");printk(KERN_INFO "Hello, world!/n");。内核中共提供了八种不同的日志级别,在linux/kernel.h中有相应的宏对应:

1
2
3
4
5
6
7
8
9
10
#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 */

#define KERN_DEFAULT KERN_SOH "d" /* the default kernel loglevel */

未指定日志级别的 printk() 采用的默认级别是DEFAULT_MESSAGE_LOGLEVEL,这个宏在kernel/printk.c中被定义为整数 4,即对应KERN_WARNING

设置日志级别

/proc/sys/kernel/printk中会有4个数值(可由echo修改),分别表示:当前控制台日志级别、未明确指定日志级别的默认消息日志级别、最小(最高)允许设置的控制台日志级别、引导时默认的日志级别。通过读写/proc/sys/kernel/printk文件可读取和修改控制台的日志级别:

1
2
3
# cat /proc/sys/kernel/printk
4 4 1 7
# echo 8 > /proc/sys/kernel/printk # 设置当前日志级别

当 printk中的消息日志级别小于当前控制台日志级别时,printk的信息(要有/n符)就会在控制台上显示。

kmsg和dmesg方法查看

但无论当前控制台日志级别是何值,通过cat /proc/kmsg(或使用dmesg)总能查看。另外如果配置好并运行了syslogdklogd,没有在控制台上显示的printk的信息也会追加到/var/log/messages.log中。

另一种使用dmesg命令来查看(新开一个shell,输入一下指令):

1
2
3
4
5
while true
> do
> sudo dmesg -c
> sleep 1
> done
  • -c:显示信息后,清除ring buffer中的内容
  • 本质为每1秒查看当前系统的日志并清空