返回所有文章
调试 / TSENGCHEN BLOG

内核通用调试技巧

02_Debug · 内核通用调试技巧

02_Debug · 第 4 / 5 篇

保留原笔记正文与技术内容,仅脱敏敏感信息。配图按作者要求保留原样。

查看内核版本

uname -a 

Pasted image 20260821153838

  • rk3576-buildroot:主机名,表示当前根文件系统是 Buildroot;它不是芯片型号的唯一证据。
  • 6.1.172:板子此刻运行的内核版本。后续编译模块时,必须首先与它核对。
  • /#2:内核构建编号。
  • SMP:内核支持多核 CPU
  • aarch64:64 位 ARM 系统
  • Mon Jul 13 … 2026:该内核的编译时间。

内核启动参数

 cat /proc/cmdline

Pasted image 20260821161928

  • storagemedia=emmc 启动介质是eMMc
  • root=PARUUID=614e0000-0000 根文件系统通过分区UUID挂载
  • earlycon=uart8250,mmio32,0x2ad40000 早期内核日志偶改UART寄存器地址
  • console = ttyFIQ0 常规内核控制台是ttyFIQ0
  • verifiedbootstate=orange 启动验证状态为 orange
  • rcu_nocbs=all 所有CPU的RCU回调倾向于写在到RCU kthread

内核导出的功能类别

ls /sys/class

Pasted image 20260824092005

  • tty:串口、终端类设备。下一课将从这里找到 ttyFIQ0、ttySx。
  • net:网络接口;CAN 成功注册后通常也会以网络接口形式出现,如 can0。
  • gpio、pwm:GPIO 控制器和 PWM 控制器的功能入口。
  • i2c-adapter、i2c-dev:I2C 控制器和用户态 I2C 设备节点接口。
  • spi_master、spidev:SPI 控制器和用户态 SPI 接口。
  • dsmc:当前内核已导出 DSMC 功能类别,适合后续工业总线/外部存储训练。
  • mmc_host:eMMC、SD、SDIO 控制器。
  • devfreq:NPU/GPU/DDR 等设备的动态调频框架入口。
  • thermal、regulator:温控与供电管理。
  • dma:DMA 引擎相关接口。

/sys

设备模型:设备是否存在、绑定谁、导出了什么功能 /sys的层图 Pasted image 20260824105155

  • /sys/blcok: 块设备设备视图,如 eMMC、SD、NVMe
  • /sys/calss: 按总线组织设备和驱动,如platform,i2c,spi,pci
  • /sys/devices:内核设备模型的真实层级,所有设备最终都能追到这里
  • /sys/fs:各文件系统导出的内核状态
  • /sys/module:已注册的内核模块及其参数
  • /sys/power:系统级电源管理接口
  • /sys/bus:按总线组织设备和驱动,如 platform、i2c、spi、pci
  • /sys/dev:字符/块设备号到 sysfs 对象的映射,较少作为首选调试入口
  • /sys/firmware:固件提供的信息;RK 平台重点是运行时 DTB
  • /sys/kernel:内核通用接口;若启用 debugfs,通常会有 /sys/kernel/debug
  • /sys/pmic、/sys/system_monitor:Rockchip BSP 的厂商扩展接口,具体内容由 PMIC/监控驱动决定

串口类设备 class

ls /sys/class/tty

Pasted image 20260824092242

  • ttyFIQ0:FIQ Debugger 提供的调试控制台,启动参数已确认它是当前的console
  • ttyS0、ttyS1等:普通uart控制器注册出来的串口节点
  • tty0:Linux虚拟终端,不是uart外设

查看ttyFIQ0 关联

关联的真实内核设备

readlink -f /sys/class/tty/ttyFIQ0/device

Pasted image 20260824092540

  • readlink:读取符号连接的目标
  • -f:递归解析所有链接,输出最终绝对路劲
  • device:这个tty功能节点实际属于哪个内核设备

查看普通uart

查看有哪些实际uart

ls -d /sys/class/tty/ttyS* 2>/dev/null

Pasted image 20260824093149

  • ls -d:列出目录本身,不展开其内部内容;
  • /sys/class/tty/ttyS*:匹配全部普通 UART;
  • 2>/dev/null:隐藏“没有匹配文件”这类非关键报错。

查看普通串口的设备

readlink -f /sys/class/tty/ttyS1/device

Pasted image 20260824093906

绑定的真实驱动

 readlink -f /sys/class/tty/ttyS0/device/driver

Pasted image 20260824094111

导出的身份信息

cat /sys/class/tty/ttyS1/device/uevet

Pasted image 20260824094831

  • DRIVER=dw-apb-uart: 表示内核已经成功把UART绑定到desginware APB uart驱动。这里的驱动名是 dw-apb- uart;其代码实现可能基于 8250 框架,但运行时应以这个实际绑定名为准。
  • OF_NAME=serial,OF_FULLNAME=/serial@27310000:设备树节点
  • OF_COMPATIBLE_0=rockchip,rk3576-uart,OF_COMPATIBLE_1=snps,dw-apb-uart:compatible列表
  • OF_ALIAS_0=serial1:表示该dts的节点别名是serial1

运行时的设备树属性

ls /sys/class/tty/ttyS1/device/of_node

Pasted image 20260824095605\

cat /sys/class/tty/ttyS1/device/of_node/status

Pasted image 20260824095825 status = “okay”;

cat /sys/class/tty/ttyS1/device/of_node/compatible

Pasted image 20260824100016

uart的中断是否注册

dmesg | grep 27310000

Pasted image 20260824101036

串口参数

stty -F /dev/ttyS1 -a

Pasted image 20260824101256

  • speed 115200 baud:当前波特率;
  • cs8:8 位数据位;
  • parenb:无校验;
  • cstopb:1 位停止位;
  • crtscts:未启用硬件 RTS/CTS 流控。

引脚

查看pinctrl

ls /sys/kernel/debug/pinctrl

Pasted image 20260824101542 查看具体引脚

grep -i uart /sys/kernel/debug/pinctrl/*/pinmux-pins

Pasted image 20260824101946

  • pin 42、pin 43:SoC 内部 pin 编号;
  • function uart1:这些引脚当前复用给 UART1;
  • group uart1m0-xfer:使用 UART1 的 mode 0 引脚组,通常至少包含 TX、RX。

检查uart时钟是否打开

grep -i uart /sys/kernel/debug/clk/clk_summary

Pasted image 20260824102526

  • enable_count / prepare_count 非 0:时钟正在被使用
  • rate 当前时钟频率,单位 Hz
  • suspended:设备被 runtime PM 挂起;访问或收发前应由驱动自动唤醒。
  • suspending:正在进入挂起。
  • unsupported:该驱动未使用 runtime PM。

查看uart 的runtime PM策略

cat /sys/class/tty/ttyS1/device/power/control

Pasted image 20260824102706

  • auto:允许内核在空闲时自动挂起 UART,节省功耗。
  • on:强制保持工作,不自动 runtime suspend。 它和刚才的 runtime_status 要结合看:
  • control=auto + runtime_status=suspended → 空闲自动休眠,通常正常
  • control=on + runtime_status=active → 强制常开,通常用于 console 或调试
  • control=auto + 实际收发失败 → 再考虑是否是 runtime PM 唤醒路径问题

通用查看

dmesg | tail -n 30
  • dmesg:内核日志;
  • tail -n 30:只看最新 30 行,避免日志太长。

驱动初始化日志

dmesg | grep -i probe

Pasted image 20260824103302

  • probe failed:初始化失败,重点看该行前后的错误码。
  • probe defer:依赖资源尚未就绪,例如 regulator、clock、GPIO 或另一个驱动;它不一定是最终故障,内核会稍后重试。

总线bus

ls /sys/bus

Pasted image 20260824111044

  • platform:SoC 内部设备,UART、I2C、SPI、CAN、DMA、显示控制器等通常在这里。
  • i2c、spi:外部 I2C/SPI 外设的设备与驱动。
  • usb、pci:可枚举总线设备。
  • mmc:eMMC、SD、SDIO 相关设备。

platform 设备列表

ls /sys/bus/platform

Pasted image 20260824140456

  • devices:挂在 platform 总线上的所有设备。
  • drivers:已注册到 platform 总线的驱动。
  • drivers_autoprobe:是否允许新设备自动匹配驱动,通常为 1。
  • drivers_probe:手动触发指定设备重新匹配驱动的入口;调试时先观察,不随意写入。
  • uevent:该总线的内核事件接口。

读取设备的内核身份卡

ls /sys/bus/platform/devices | head
readlink -f /sys/bus/platform/devices/27310000.serial
cat /sys/devices/platform/27310000.serial/uevent

Pasted image 20260824142014 调试意义:

  • DRIVER → 实际绑定的驱动,不靠猜
  • OF_FULLNAME → 实际运行时 DTS 节点
  • OF_COMPATIBLE_0 → 驱动匹配依据;compatible 写错会导致无驱动绑定
  • MODALIAS → 内核自动匹配模块时使用的标识

/proc

/proc 查看系统是否有资源压力 中断、内存、任务、网络等运行状态是否异常

查看系统内存

head -n 10 /proc/meminfo

Pasted image 20260824143824

  • MemTotal:内核可用的总 RAM,不一定等于物理标称容量。
  • MemFree:完全空闲内存;小不一定有问题。
  • MemAvailable:估计可立即供新程序使用的内存,更适合判断内存压力。
  • Buffers、Cached:文件缓存,可在内存紧张时回收。
  • Slab:内核对象缓存;异常持续增长时才怀疑内核内存泄漏。
  • SwapTotal / SwapFree:交换空间容量和剩余量。

查看CPU调度

cat /proc/loadavg

Pasted image 20260824144500

  • 0.03 最近 1 分钟平均负载
  • 0.02 最近 5 分钟平均负载
  • 0.00 最近 15 分钟平均负载
  • 1/202 当前参与调度的任务数 / 系统总任务数
  • 1865 最近创建的进程 PID

软中断统计

head -n 5 /proc/softirqs

Pasted image 20260824144805

  • HI: CPU0=2039,其余几乎为 0
  • TIMER: CPU1、CPU5 较高
  • NET_TX: 全部为 0
  • NET_RX: 全部很低

块设备软中断

grep BLOCK /proc/softirqs

Pasted image 20260824150542

进程卡在内核哪个等待点

 cat /proc/$$/wchan
 cat /proc/<pid>wchan

Pasted image 20260824151427

  • futex_wait_queue_me → 等待锁或条件变量
  • io_schedule → 等待存储 I/O
  • ep_poll → 等待 epoll 事件
  • do_wait → 等待子进程结束

进程的内核调用栈

cat /proc/$$/stack
cat /proc/<pid>/stack

Pasted image 20260824152011

debugfs

ftrace

cat /sys/kernel/debug/tracing/current_tracer

Pasted image 20260824152456

  • nop:当前没有启用函数跟踪,正常。
  • function:正在记录内核函数进入。
  • function_graph:正在记录函数调用关系与耗时。
  • 其他值:可能有调度、事件等专用 tracer 在运行。

按驱动打开日志

grep 8250_dw /sys/kernel/debug/dynamic_debug/control

Pasted image 20260824155952

  • Designware UART version …:读取到 UART 的 DesignWare 版本信息。
  • CPR is not available …:硬件的组件参数寄存器不可读时,驱动采用备用参数继续初始化。 打开debug打印
echo 'file drivers/tty/serial/8250/8250_dwlib.c +p' > /sys/kernel/debug/dynamic_debug/control
grep 8250_dw /sys/kernel/debug/dynamic_debug/control

file …8250_dwlib.c 只选择这个源码文件,+p 打开 pr_debug/dev_dbg 打印 Pasted image 20260824161239

调度子系统可跟踪的事件

ls /sys/kernel/debug/tracing/events/sched

Pasted image 20260824161950

  • sched_switch:CPU 从一个任务切换到另一个任务。
  • sched_wakeup:任务被唤醒、进入可运行状态。
  • sched_waking:唤醒过程开始。
  • sched_migrate_task:任务在 CPU 之间迁移。
02_Debug · 文档目录
上一篇2026-07-30_RK3572_RK1828_PCIe驱动匹配客户内核编译下一篇RK3506B-EVB1 DSMC