土法炼钢兴趣小组的算法知识备份

【操作系统百科】内核日志

文章导航

分类入口
os
标签入口
#printk#dmesg#netconsole#dev-printk#kernel-logging

目录

printk 是内核最古老的调试工具——从 0.01 版本就存在。但它的实现远比想象的复杂。

一、先看图

flowchart LR
    KERN[内核代码] -->|printk| RINGBUF[环形缓冲区<br/>__log_buf]
    RINGBUF --> CONSOLE[控制台<br/>串口/VGA]
    RINGBUF --> KMSG[/dev/kmsg]
    KMSG --> JOURNALD[systemd-journald]
    RINGBUF --> NETCON[netconsole<br/>UDP 远程]

    classDef kern fill:#388bfd22,stroke:#388bfd,color:#adbac7;
    classDef out fill:#3fb95022,stroke:#3fb950,color:#adbac7;
    class KERN,RINGBUF kern
    class CONSOLE,KMSG,JOURNALD,NETCON out

二、printk 基础

printk(KERN_ERR "Error: %s failed with %d\n", name, ret);
pr_err("Error: %s failed with %d\n", name, ret);      // 推荐
dev_err(dev, "failed with %d\n", ret);                  // 设备相关

2.1 日志级别

级别 含义
0 KERN_EMERG 紧急
1 KERN_ALERT 警报
2 KERN_CRIT 严重
3 KERN_ERR 错误
4 KERN_WARNING 警告
5 KERN_NOTICE 通知
6 KERN_INFO 信息
7 KERN_DEBUG 调试

三、环形缓冲区

# 缓冲区大小(默认 1MB)
dmesg | wc -c
# 或内核参数
log_buf_len=4M

固定大小环形缓冲区 → 满了就覆盖旧的。

// kernel/printk/printk.c
static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN);

四、dev_printk 系列

dev_info(dev, "device initialized\n");
dev_warn(dev, "firmware version %d is old\n", ver);
dev_err(dev, "probe failed: %d\n", ret);

自动包含设备信息(bus、device name)→ 方便过滤。

五、Rate Limiting

printk_ratelimited(KERN_WARNING "too many retries\n");
// 或
if (net_ratelimit())
    pr_warn("packet dropped\n");

防止日志洪水 → 默认 10 条/5 秒。

六、netconsole

# 内核参数
netconsole=@192.168.1.1/eth0,@192.168.1.2/aa:bb:cc:dd:ee:ff

# 或模块
modprobe netconsole netconsole=@192.168.1.1/eth0,6666@192.168.1.2/

通过 UDP 发送内核日志到远程 → panic 时也能看到最后的消息(如果网络还活着)。

七、printk lockless 改造

传统 printk 使用 logbuf_lock → 高频打印可能造成延迟。

Linux 5.10+ 改为 lockless ring buffer:

// kernel/printk/printk_ringbuffer.c
struct printk_ringbuffer

结构化日志记录 → 每条消息包含时间戳、级别、设备信息。

八、/dev/kmsg 与 journald

cat /dev/kmsg          # 结构化格式
dmesg                  # 传统格式
journalctl -k          # 通过 journald 读取

systemd-journald 从 /dev/kmsg 读取 → 合并内核和用户态日志 → 统一查询。

九、观察

dmesg -T                      # 人类可读时间
dmesg --level=err             # 只看错误
dmesg -w                      # 实时跟踪

# 控制台级别
cat /proc/sys/kernel/printk
# current default minimum boot-time-default

# 动态调试
echo 'file drivers/nvme/* +p' > /sys/kernel/debug/dynamic_debug/control

十、小结


参考文献

工具


上一篇lockdep 下一篇/proc 与 /sys

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-05-06 · os

【操作系统百科】内核内存调试

内核内存 bug 是最难追的:UAF、OOB、double free、leak 都可能沉默数月。本文讲 KASAN 三种模式、KFENCE 生产采样、kmemleak、SLUB_DEBUG、UBSAN/KCSAN 联动。

2026-05-08 · os

【操作系统百科】VFS 四层抽象

Linux 的一切皆文件靠 VFS 实现——superblock、inode、dentry、file 四层抽象加 ops 表。本文讲 VFS 核心数据结构、dcache、inode cache、RCU lookup,以及文件系统如何插入 VFS。

2026-04-22 · os

操作系统百科

Linux 6.x 视角下的操作系统系列索引:110 篇覆盖调度、虚拟内存、文件系统与 I/O、并发、隔离、可观测性,按主题、阅读路径与关键问题三种入口组织。

2026-05-27 · os

【操作系统百科】用户态分配器:jemalloc vs tcmalloc

jemalloc 与 tcmalloc 都想解决多线程分配器的老问题:锁争抢、碎片、RSS 膨胀与回收抖动。但两者把优化重点放在了不同位置:tcmalloc 更激进地把热路径推到 per-CPU,jemalloc 则把 arena、extent、decay 和 profiling 做成了一套更完整的内存治理工具箱。


By .