kernel printk的打印等级

前言

在程序开发中最常用的调试手段就是打印,同时也可向我们输出提示消息。在应用层采用printf用于打印,
在内核开发中我们用printk来进行打印,而内核的打印是有等级的,本篇文章就是介绍内核的打印等级。

驱动

编写一个简单的驱动

打印等级的定义在kernel\include\linux\kern_levels.h

#include<linux/init.h>
#include<linux/module.h>

static int __init hello_init(void)
{
    
    
    printk(KERN_EMERG "LOG level 0\r\n");
	printk(KERN_ALERT "LOG level 1\r\n");
	printk(KERN_CRIT "LOG level 2\r\n");
	printk(KERN_ERR "LOG level 3\r\n");
	printk(KERN_WARNING "LOG level 4\r\n");
	printk(KERN_NOTICE "LOG level 5\r\n");
	printk(KERN_INFO "LOG level 6\r\n");
	printk(KERN_DEBUG "LOG level 7\r\n");
	printk("-------------------\r\n");
	printk("defaule LOG level\r\n");
    return 0;
}

static void __exit hello_exit(void)
{
    
    
    printk("--exit:----%s-------\r\n",__FUNCTION__);
    
}


module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

驱动很简单insmod的时候打印一些信息在控制台上
printk的格式等级与msg之间用空格隔开
printk也可不加等级,内核将采用默认等级

makefile


MOD_NAME := akk_printk

obj-m += $(MOD_NAME).o 
$(MOD_NAME)-objs += ko_printk_log_level.o

MAKE_ENV = ARCH=arm64 CROSS_COMPILE=aarch64-XXXX-linux-
KERNEL_DIR = XXX/kernel
.PHONY: all clean

all:
	make -C $(KERNEL_DIR) M=`pwd` $(MAKE_ENV) modules
	
clean:
	rm -rf .tmp_versions *.mod.* *.o .*.mod .*.ko.cmd .*.o.cmd  Module.symvers modules.order  *.ko

测试

将上述的驱动在内核下insmod你会发现并不是所有的printk都打印出来了。这里涉及到一个内核的打印策略
内核的printk模块它维护了一个数组,里面的值可以看做配置,这种配置指导打印哪些内容打印哪些内容不打印。

//\kernel\kernel\printk\printk.c
int console_printk[4] = {
    
    
	CONSOLE_LOGLEVEL_DEFAULT,		/* console_loglevel 		7*/
	MESSAGE_LOGLEVEL_DEFAULT,	/* default_message_loglevel 	CONFIG_MESSAGE_LOGLEVEL_DEFAULT*/
	CONSOLE_LOGLEVEL_MIN,		/* minimum_console_loglevel 	1*/
	CONSOLE_LOGLEVEL_DEFAULT,	/* default_console_loglevel 	7*/
};
//\kernel\include\linux\printk.h
/* printk's without a loglevel use this.. */
#define MESSAGE_LOGLEVEL_DEFAULT CONFIG_MESSAGE_LOGLEVEL_DEFAULT

#define CONSOLE_LOGLEVEL_SILENT  0 /* Mum's the word */
#define CONSOLE_LOGLEVEL_MIN	 1 /* Minimum loglevel we let people use */
#define CONSOLE_LOGLEVEL_QUIET	 4 /* Shhh ..., when booted with "quiet" */
#define CONSOLE_LOGLEVEL_DEFAULT 7 /* anything MORE serious than KERN_DEBUG */

从上述可以看出数组中元素的含义为,控制台的打印等级、默认的打印等级、用户最小可配置打印等级、默认的控制台打印等级,后面这两个等级配置我到现在也不是很明白干嘛用的。

重点分析

这个配置数组console_printk的值可以在内核下看到命令
$ cat /proc/sys/kernel/printk
7 4 1 7
这个是内核代码中的默认配置值,第二个元素MESSAGE_LOGLEVEL_DEFAULT还可以在内核的menuconfig 中配置
同时也可以动态的修改内核当前的打印配置,echo后再次进行cat就能看到配置修改生效
echo “8 4 1 7” > /proc/sys/kernel/printk

这个时候再次挂载我们之前的驱动就能看到所有的打印了。

内核的打印策略,当消息的打印优先级大于我内核的控制台打印等级我就打印输出。否者不输出
这里数字越低表示优先级越高
可以类比代码,消息的打印等级值 < 控制台打印等级值 ? 输出 : 不输出;
可以看出与控制台的打印相等也不输出

这个时候可以回头来看配置的第一个值 7 表示当前内核打印输出的等级为7,只有等级0—6的消息才会输出到控制台,
这个配置可以用来控制内核的打印,有些场景不希望内核有打印那么就可以设置这个值来做。

疑问

那有些消息不打印出来的话,但我想看,那岂不是看不到了,放心,内核的消息肯定是能够看到的,
所有的内核打印以及printk的输出都会缓存到内核的一个console-buff中,上面的控制台消息打印配置,其实就是在这个buf中有哪些数据可以让你直接看到而已。
通过内核的命令dmesg就能看到所有的打印消息了。

Guess you like

Origin blog.csdn.net/weixin_41884251/article/details/116034161