printk、dmesg、rsyslog相关知识总结

举报
媒体服务小助手ultra 发表于 2023/09/13 10:09:11 2023/09/13
【摘要】 printk是内核日志打印的函数。如果编译内核时选择了CONFIG_PRINTK=y,则会增加这个功能,否则所有printk都会被替换成空语句。不过放心,当前suse和euler都已经开启了这个选项。1、日志源printk的实现是将字符串格式化之后,拷贝到全局环形缓冲区 log_buf 中。用户态程序可以使用syslog(type=2 or 3 or 4)系统调用从内核环形缓冲区中读取这个日...

printk是内核日志打印的函数。

如果编译内核时选择了CONFIG_PRINTK=y,则会增加这个功能,否则所有printk都会被替换成空语句。
不过放心,当前suse和euler都已经开启了这个选项。

1、日志源
printk的实现是将字符串格式化之后,拷贝到全局环形缓冲区 log_buf 中。

用户态程序可以使用syslog(type=2 or 3 or 4)系统调用从内核环形缓冲区中读取这个日志。

rsyslog从/proc/kmsg中持续读取(通过select来poll),并写入/var/log/messages文件(通过/etc/rsyslog.conf配置)。

dmesg从/dev/kmsg中读取。
cat /dev/kmsg可以获得和dmesg几乎同样的效果,区别是命令最后会阻塞住等待新日志并持续打印。

通过修改系统配置 echo off > /proc/sys/kernel/printk_devkmsg 可以禁止从 /dev/kmsg 文件读取。
有三个可选值 on、off、ratelimit,默认是 ratelimit。

也可以通过系统启动参数 printk.devkmsg=on 或者 printk.devkmsg=off 来控制。
不过这样的话,/proc/sys/kernel/printk_devkmsg就无法被修改了。

2、内核日志环形缓冲区大小
默认内核日志环形缓冲区大小是编译内核时通过CONFIG_LOG_BUF_SHIFT宏进行控制的。
suse配置的18(1<<18=256KB),euler配置的20(1<<20=1MB)。

通过系统启动参数log_buf_len=n,可以设置内核日志环形缓冲区大小为n字节。
通过系统启动参数nmi_log_buf_len=n,可以设置内核在nmi上下文打印日志时使用的环形缓冲区大小为n字节。

3、日志级别
printk 有八个日志优先级,分别是 0 KERN_EMERG、1 KERN_ALERT、2 KERN_CRIT、3 KERN_ERROR、4 KERN_WARNING、5 KERN_NOTICE、6 KERN_INFO、7 KERN_DEBUG。

系统配置文件 /proc/sys/kernel/printk 记录了四个日志级别相关的参数,对应内核变量console_printk。
int console_printk[4] = {
DEFAULT_CONSOLE_LOGLEVEL, // 日志级别小于这个值,就打印到console上
DEFAULT_MESSAGE_LOGLEVEL, // 当使用 printk(KERN_DEFAULT) 打印日志的时候,就使用这个loglevel
MINIMUM_CONSOLE_LOGLEVEL, // console日志级别最小值
DEFAULT_CONSOLE_LOGLEVEL, // 默认console日志级别
};

和日志级别相关的内核启动参数有
1、debug(将console loglevel设置为10)
2、quiet(将console loglevel设置为4)
3、loglevel=n(将console loglevel设置为n)

在/etc/rsyslog.conf中,有个配置项$klogConsoleLogLevel配置为1,所以rsyslog会把/proc/sys/kernel/printk第一个值改为1 。因此默认只有KERN_EMERG的日志会打印在console上。

rsyslog从/proc/kmsg读取,是直接从内核日志缓冲区读取的。根据/etc/rsyslog.conf,一般来说所有的内核日志都会打印到/var/log/messages。

dmesg从/dev/kmsg读取,也是直接从内核日志缓冲区读取的,所以所有内核日志都能通过dmesg查看。

有一个例外,将在动态debug日志部分讲到。

4、动态debug日志
如果使用printk(KERN_DEBUG)打印日志,不叫动态debug日志(我们先称为静态debug日志)。
通过pr_debug或者dynamic_pr_debug打印的日志,才叫动态debug日志。

默认情况下,静态debug日志通过dmesg是可以查看的,动态debug日志是看不到的。
开启动态debug日志特性,需要在内核编译的时候选择CONFIG_DYNAMIC_DEBUG=y。
如果没有打开这个特性,pr_debug或者dynamic_pr_debug都不会有任何打印。
suse和euler都已打开此特性。

这个编译选项不控制静态debug日志。通过printk(KERN_DEBUG)打印的日志,默认是能够通过dmesg和/var/log/messages看到的。

而动态debug日志默认不打印。内核提供了配置文件/sys/kernel/debug/dynamic_debug/control来单独控制每个debug日志是否能够打印。


具体可以参考内核文档【suse】Document/dynamic-debug-howto.txt,或者【euler】Documentation/admin-guide/dynamic-debug-howto.rst,或者3ms链接 http://3ms.huawei.com/km/blogs/details/5523725

5、日志流控
如果你发现一个日志频繁打印影响了系统性能,那可能需要增加日志流控。

通过带_ratelimited后缀的日志函数打印日志(如printk_ratelimited、pr_emerg_ratelimited_ratelimited、pr_alert_ratelimited、pr_crit_ratelimited、pr_err_ratelimited、pr_warn_ratelimited、pr_notice_ratelimited、pr_info_ratelimited、pr_debug_ratelimited等),是可以做到日志流控的。

控制策略是默认写死的,每5秒(DEFAULT_RATELIMIT_INTERVAL)最多打印10条日志(DEFAULT_RATELIMIT_BURST)。

END

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。