Linux kernel printk log level
1. Log level 的定义
在 Linux 内核里,printk 经常用来格式化输出,类似于常见的 printf。需要注意的是,printk 有一个 log level 的参数,使用的时候经常是这样的:
printk(KERN_WARNING "Trying to free nonexistent resource");
浏览内核头文件,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 */
使用的时候要选择合适的 level。
既然打印时指定了不同的 log level,那系统运行时,可以屏蔽到一些打印,从而实现日志的过滤。默认的过滤级别是 CONSOLE_LOGLEVEL_DEFAULT。这个值定义在 defconfig 里。
如果在调用 printk 时没有指定,会使用默认的 MESSAGE_LOGLEVEL_DEFAULT。这个值同样定义在 defconfig 里。
2. 调整 log level
系统运行过程中,可以通过 /proc/sys/kernel/printk
文件,来查看和调整运行时的 log level:
$ cat /proc/sys/kernel/printk
4 4 1 7
这四个数值,分别是:
- 目前的控制台的 log level。日志的 log level 小于(优先级高于)这个值的时候,才会输出;
- 默认的 log level,如果调用 printk 时没有指定的话;
- 第 1 个参数可以设置的最小值;
- boot 时的 log level,尽量大(优先级低)一些,从而可以看到更多启动日志;
如果要修改,用 echo 就可以了。
3. Kernel 里的相关代码
log level 数组定义 @ kernel/printk/printk.c
int console_printk[4] = {
CONSOLE_LOGLEVEL_DEFAULT, /* console_loglevel */
MESSAGE_LOGLEVEL_DEFAULT, /* default_message_loglevel */
CONSOLE_LOGLEVEL_MIN, /* minimum_console_loglevel */
CONSOLE_LOGLEVEL_DEFAULT, /* default_console_loglevel */
};
EXPORT_SYMBOL_GPL(console_printk);
console_printk @ include/linux/printk.h
extern int console_printk[];
#define console_loglevel (console_printk[0])
读写 /proc/sys/kernel/printk 的实现 @ kernel/sysctl.c
{
.procname = "printk",
.data = &console_loglevel,
...
},
参考资料
- Documentation/admin-guide/sysctl/kernel.rst, printk
- man 2 syslog