lockdep在首次发现非法锁依赖时立即打印警告至dmesg,/proc/lockdep仅提供当前锁依赖图快照;必须启用CONFIG_PROVE_LOCKING=y才能触发完整死锁告警,其输出含调用栈与锁路径,而非生成报告文件。

内核死锁触发后,/proc/lockdep 和 dmesg 是主报告来源
Linux 内核启用 lockdep 后,一旦检测到潜在死锁(如 AB-BA 锁顺序冲突、递归加锁),不会等程序卡死才报警——它会在**首次发现非法锁依赖时立即打印警告**,并记录到内核日志。这不是事后分析,而是运行时主动拦截。
关键点:lockdep 不生成“报告文件”,它的输出直接刷进内核环形缓冲区,必须用 dmesg 实时抓取;而 /proc/lockdep 是只读状态快照,反映当前已注册的锁依赖图,不包含错误上下文。
-
dmesg | grep -i "lock.*dep\|deadlock\|circular"—— 最快定位是否触发过警告 - 完整死锁警告通常以
WARNING: possible circular locking dependency detected开头,后面紧跟着完整的调用栈、持锁线程、等待锁路径 - 若系统已 hang 住但终端无响应,需通过串口或 crash shell(如 kdump)进入,再执行
dmesg -T查带时间戳的原始日志 -
/proc/lockdep仅显示当前所有锁的依赖关系拓扑,没报错时也存在;它不能告诉你哪次加锁出问题,只供人工比对锁序
CONFIG_PROVE_LOCKING=y 才能输出详细死锁现场
默认内核配置(如发行版 kernel)通常关闭深度锁验证。没有 CONFIG_PROVE_LOCKING=y,lockdep 只做轻量级检查,不会遍历所有锁路径组合,也就不会触发循环依赖告警。
这意味着:你看到 /proc/lockdep 存在,不代表它能捕获死锁;必须确认该选项已编译进内核。
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
- 检查方法:
zcat /proc/config.gz | grep CONFIG_PROVE_LOCKING(若支持 config.gz)或grep CONFIG_PROVE_LOCKING /boot/config-$(uname -r) - 输出应为
CONFIG_PROVE_LOCKING=y,不是=m或未定义 - 该选项依赖
CONFIG_LOCKDEP=y和CONFIG_DEBUG_LOCK_ALLOC=y,三者缺一不可 - 开启后性能开销明显(约 10–20% 调度延迟),生产环境慎用,调试环境必备
用户态死锁没有内核级报告,得靠 gdb + pstack 推断
应用层(如 C/C++ pthread 程序)发生的死锁,内核完全不知情——它只看到线程在 futex_wait 或 __pthread_mutex_lock 系统调用里休眠。此时 dmesg 干净,/proc/lockdep 为空,一切“正常”。
真正线索藏在线程栈里:哪个线程卡在 pthread_mutex_lock?它等的是哪个地址的 mutex?谁又正持有那个地址?
- 先用
ps aux | grep your_app找 PID,再pstack <pid></pid>看所有线程栈 —— 关键看帧中是否出现__pthread_mutex_lock或sem_wait - 若
pstack不可用,用gdb -p <pid></pid>进去执行info threads+thread apply all bt - 重点比对:线程 A 栈顶等
mutex_B地址,线程 B 栈顶等mutex_A地址,且各自上一帧显示刚 lock 了对方要的锁 → 基本锁定 AB-BA - 注意:
gdb必须附加到正在阻塞的进程,不是启动时调试;否则看不到真实等待态
别指望 strace 或 ltrace 直接暴露死锁
strace 显示系统调用进出,ltrace 显示动态库函数调用,它们对死锁诊断只有间接价值:
-
strace -p <pid> -e trace=futex,pread,pwrite</pid>可看到线程反复陷入futex(FUTEX_WAIT_PRIVATE),说明在等内核同步原语,但看不出等谁、为什么等 -
ltrace -p <pid> -e "pthread_mutex_*"</pid>可能截获pthread_mutex_lock返回前的卡顿,但无法关联到具体锁变量,更无法跨线程追踪持有关系 - 二者都可能因高频率 syscall 冲刷日志,掩盖关键帧;且多线程下输出混杂,需配合
-s 1024 -o trace.log重定向后人工筛选 - 真正有效的是把
pstack输出和源码行号对照,定位到pthread_mutex_lock(&lockA)这一行,再顺藤摸瓜查 lockA 被谁 hold
死锁调试最易被忽略的点:你以为在看“谁卡住了”,其实关键在“谁没放手”。所有工具都只能告诉你等待侧,释放侧必须靠代码审计或内存地址交叉验证——而后者,往往就差一个 gdb p/x &lockA 和 info proc mappings 的组合。

















