点击上方蓝字关注我们
点击上方蓝字关注我们
cpu: i.mx8mq OS:Android 11 Kernel version:kernel 5.10
1. 初识Printk
printk
是Linux内核中用于输出日志消息的核心函数。作为内核调试和信息记录的关键工具,printk
提供了一种在内核空间中输出信息的机制。printk
与平时常用的printf
的用法非常相似,主要用于调试、性能分析以及记录内核运行时的各种信息,帮助开发人员理解系统行为和解决问题。图1.1 printk 流程
从图中可以看到prink
主要有两个方面:
一部分是输出 Log
到log_buf
这里是指将所有的级别的log都会存储到缓冲区当中,该缓冲区在/proc/kmsg
,缓冲区是有大小,当缓冲区满了将会覆盖旧的部分,缓冲区大小设置通过配置CONFIG_LOG_BUF_SHIFT
另外一部分是输出 Log
到Console
,这里的所有的日志不一定将会输出,而是由loglevel进行控制了。日志到了Console
可以通过串口进行输出,串口的打开关闭也就控制了串口的日志输出,另外还可以到达RAM Console
,这对于在内核启动过程中、在控制台不可用的情况下以及在非交互性环境中记录日志非常有用。
2. Printk的日志级别以及设置
2.1 日志级别
根据内核源码:
"include/linux/kern_levels.h"
KERN_EMERG
是级别最高的,KERN_DEBUG
等级是最低的,最高级别的日志信息需要特别关注。在内核配置中可以通过配置参数CONFIG_MESSAGE_LOGLEVEL_DEFAULT
进行配置输出等级,一般默认为4
2.2 日志级别设置
/proc/sys/kernel/printk
修改,cat /proc/sys/kernel/printk
7 4 1 7
第一个数字( console loglevel
):控制台消息的显示级别,这里显示7表示控制台消息级别;第二个数字( default message log level
):默认消息的显示级别,这里显示为4;第三个数字( minimum allowed console log level
):允许的最小控制台消息级别,设置为1;第四个数字( default console log level
):默认的控制台消息级别,级别为7;
console loglevel
设置为6
,debue 信息不需要打印那么设置为:echo "6 4 1 7" > /proc/sys/kernel/printk
/etc/sysctl.conf
,添加或修改以下行:kernel.printk = "6 4 1 7"
在运行命令:
sysctl -p
日志设置将会在重新启动后生效。
方法3:
可以通过uboot 设置bootargs
来传递内核启动参数,这里可以采用在UBoot中进行设置:
setenv bootargs ${bootargs} loglevel=X
saveenv
setenv bootargs ${bootargs} loglevel=X
X表示日志级别;3. 常见使用方法
在开发的过程中,会发现linux 内核中很多不是直接使用prink这个函数,而是重新定义这个函数,但都是基于printk去实现。为什么这样,主要是可以更加方便,对于驱动设备可以方便打印模块,有的是为了简化日志的的级别。
3.1 pr_xx系列
/*
* #defines for all the dev_<level> macros to prefix with whatever
* possible use of #define dev_fmt(fmt) ...
*/
#define dev_emerg(dev, fmt, ...) \
_dev_emerg(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_crit(dev, fmt, ...) \
_dev_crit(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_alert(dev, fmt, ...) \
_dev_alert(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_err(dev, fmt, ...) \
_dev_err(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_warn(dev, fmt, ...) \
_dev_warn(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_notice(dev, fmt, ...) \
_dev_notice(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_info(dev, fmt, ...) \
_dev_info(dev, dev_fmt(fmt), ##__VA_ARGS__)
#if defined(CONFIG_DYNAMIC_DEBUG) || \
(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
#define dev_dbg(dev, fmt, ...) \
dynamic_dev_dbg(dev, dev_fmt(fmt), ##__VA_ARGS__)
#elif defined(DEBUG)
#define dev_dbg(dev, fmt, ...) \
dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__)
#else
#define dev_dbg(dev, fmt, ...) \
({ \
if (0) \
dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__); \
})
#endif
4. 总结
往期回顾:
有兴趣加入嵌入式软件交流群