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

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

文章导航

分类入口
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-04-27 · os

【操作系统百科】内存回收

Linux 内存回收是 VM 最复杂的子系统之一。本文讲 active/inactive LRU、kswapd 与 direct reclaim、watermark 三线、swappiness 的真实含义、MGLRU 改造、memcg 回收与 PSI。

2026-04-28 · os

【操作系统百科】交换

swap 还值得开吗?本文讲 swap area 基础、swap cache、zram 压缩内存、zswap 前端压缩池、swappiness 的真实含义、容器里的 swap 策略,以及为什么现代 Android 全靠 zram 不靠磁盘。

2026-05-03 · os

【操作系统百科】Slab/SLUB 分配器

buddy 只管页粒度(4K+),内核大多数对象只有几十到几百字节。slab/SLUB 在 buddy 之上做对象级缓存。本文讲 slab 历史、SLUB 接手、SLOB 退场、kmem_cache、per-CPU cache、KASAN 集成。

2026-05-07 · os

【操作系统百科】用户态分配器

glibc malloc、tcmalloc、jemalloc、mimalloc 各有哲学。本文讲 arena、thread cache、size class、madvise 返还策略、碎片与 RSS 膨胀、如何根据负载选分配器。


By .