Linux kernel:修改内核 printk 日志等级
1. 背景
我们进行驱动和内核开发时,最常用的调试手段就是 printk()。该函数支持多个等级的日志级别,不同的内核配置会修改相应的日志级别,最终影响终端显示的日志信息。因此我们很有必要知道如何修改日志级别,以达到显示或屏蔽显示日志的目的。
1.1 测试环境:
Kernel version:5.10.0(Xilinx petalinux-2021.2)
1.2 内核模块:
这里使用上篇文章中的 hello 驱动。该驱动中使用 KERN_DEBUG 模式持续输出调试信息。通过修改系统中对应文件的内容达到影响 printk() 的目的,最终可看到 hello 驱动中调试信息的有无。
2. 日志等级说明
Linux 内核中,日志等级定义在 include/linux/kern_levels.h 文件中。数值越小等级越高。
级别 | 对应内核日志级别 | 说明 |
0 | KERN_EMERG | 紧急消息。系统崩溃之前提示,表示系统已不可用。 |
1 | KERN_ALERT | 报告消息。表示必须立即采取措施。 |
2 | KERN_CRIT | 临界消息。通常涉及严重的硬件或软件操作失败。 |
3 | KERN_ERR | 错误消息。串口日志的默认级别。驱动程序常用 KERN_ERR 来报告硬件的错误。 |
4 | KERN_WARNING | 警告消息。对可能出现问题的情况进行警告。 |
5 | KERN_NOTICE | 正常但又重要的消息。用于提醒,常用于与安全相关的消息。 |
6 | KERN_INFO | 提示消息。如驱动程序启动时,打印硬件消息。 |
7 | KERN_DEBUG | 调试消息。设置此级别会打印所有日志消息。 |
3. 查看系统使用的日志等级信息
通常情况下,上述命令会输出 7 4 1 7
。这四个数字依次对应 console_loglevel,default_message_loglevel,minimum_console_loglevel,default_console_loglevel。
console_loglevel:控制台使用的日志级别;
default_message_loglevel:调用 printk() 未指定日志级别时使用的日志级别;
minimum_console_loglevel:允许设置的控制台日志级别(console_loglevel)最小值;
default_console_loglevel:系统启动时使用的日志级别。
4. 修改日志等级
通常情况下,为了加速系统启动,系统的启动信息会非常少。比如 default_console_loglevel 和 console_loglevel 为 4 的情况下,只能显示 err、crit、alert 和 emerg 等调式信息。这给内核模块的调式带来极大的不便。系统启动后,为了能够自如的控制调试信息的显示,我们有必要学习如何修改内核日志等级,以达到显示调试信息的目的。主要有以下几种实现方式。
4.1 proc/sys/kernel/printk
cat proc/sys/kernel/printk
可以显示当前内核日志等级信息。同时,使用 echo 命令能够控制对应的日志等级。
比如,编译内核前,设置了 default_console_loglevel 为 4。系统启动后,我们想要显示 debug 级别的信息,那么我们可以使用如下命令:
为什么是 8 呢,KERNEL_DEBUG 的值不是 7 么?因为控制台(console)只会显示大于所设置等级的信息。比如只显示 alert 和 emerg 级别的信息,那么 console_loglevel 应该设置为 2。同样的,想要显示 debug 信息,console_loglevel 应设置为**大于 7 **的值。
系统重启后上述修改会丢失。
4.2 dmesg
dmesg -n <value>
和 echo x > proc/sys/kernel/printk
能够达到同样的效果。同样,系统重启后修改会丢失。
4.3 sysctl
4.3.1 临时修改
sysctl -w kernel.printk=xx
。该种方式和前面的两种方式达到的效果相同。同样的,系统重启后修改会丢失。
4.3.2 永久修改
sysctl 依据 etc/sysctl.conf 文件配置内核,比如可以通过配置该文件修改 socket 接收缓冲区大小。如果向该文件中加入 kernel.printk = 3 4 1 7,那么系统启动后串口终端只会显示 crit、alert、emerg 这三个等级的日志信息。
由于修改的系统配置文件,因此,系统重启后修改会保留并生效。
4.4 menuconfig
生成内核 image 之前,可以使用 make menuconfig
配置 default_console_loglevel 选项。比如配置为显示 debug 级别的信息,可以修改为如下设置。
通过内核中如下源码可知,console_loglevel 和 default_console_loglevel 值相同。因此内核启动后,使用 cat proc/sys/kernel/printk
可以得到 8 4 1 8
4.5 kernel parameter
4.5.1 loglevel
通过在内核启动参数 bootargs 中添加 loglevel=xx
也可以达到修改日志级别的功能。
比如,我们在内核中将 console_loglevel 设置为 4,然后在 bootargs 中添加 loglevel=8
。启动系统并登录后,在串口同样可以看到 hkm thread run 的信息。需要注意的是,这种方式设置的 loglevel
只会设置 console_loglevel 的值,不会设置 default_console_loglevel。
4.5.2 ignore_loglevel
也可以在内核启动参数中标明 ignore_loglevel
,也能达到 loglevel=8
的效果。
5. 总结
不管设置的日志级别为何值,dmesg
命令总是能显示所有日志信息;
如果要修改系统启动时的日志显示,那么只能通过修改内核选项(make menuconfig) 或修改启动参数(bootargs)达到此目的;
系统启动后,可通过 echo x > /proc/sys/kernel/printk、dmesg -n x、sysctl -w kernel.printk=x临时修改日志显示级别。如果要永久修改,可以将 kernel.printk = x x x x 写入 /etc/sysctl.conf 文件中。
转载自:
更多推荐
所有评论(0)