[Linux]学习笔记系列 -- [kernel][lock]debug_locks
title: debug_locks
categories:
- linux
- kernel
- lock
tags: - linux
- kernel
- lock
abbrlink: a3bbff77
date: 2025-10-03 09:01:49
文章目录
- debug_locks
- **debug_locks 的介绍**
- **特点**
- **使用场景**
- **工作原理**
- **1. 全局标志控制**
- **2. 锁调试关闭函数**
- **3. 锁错误检测**
- **4. 锁调试关闭的通用函数**
- **总结**
- lib/debug_locks.c
- include/linux/debug_locks.h
- DEBUG_LOCKS_WARN_ON

https://github.com/wdfk-prog/linux-study
debug_locks
- 各种锁的常用调试工具的通用位置: 自旋锁、rwlocks、mutex 和 rwsems。
debug_locks 的介绍
debug_locks
是 Linux 内核中用于调试各种锁(如自旋锁、自读写锁、互斥锁和读写信号量)的工具。它提供了一种机制,用于检测锁的使用错误,并在发现问题时记录或报告相关信息。
特点
- 全局控制:通过全局标志
debug_locks
,可以一次性启用或禁用所有锁的调试功能。 - 静默模式:支持通过
debug_locks_silent
实现“静默失败”,即在检测到锁错误时不打印任何信息到控制台。 - 原子操作:使用
xchg
等原子操作确保在多线程环境中安全地切换调试状态。 - 减少噪声:在检测到第一个锁错误后,可以关闭后续的调试输出,避免日志被大量错误信息淹没。
使用场景
-
锁错误检测:
- 在开发和调试阶段,用于检测锁的使用错误,例如死锁、锁未正确释放等问题。
- 适用于调试自旋锁(
spinlock
)、读写锁(rwlock
)、互斥锁(mutex
)和读写信号量(rwsem
)等。
-
内核模块开发:
- 在开发内核模块时,
debug_locks
可以帮助开发者快速发现锁的使用问题,避免潜在的竞争条件或死锁。
- 在开发内核模块时,
-
内核稳定性测试:
- 在运行内核测试套件时,
debug_locks
可以捕获锁相关的错误,确保内核的稳定性和可靠性。
- 在运行内核测试套件时,
-
生产环境问题排查:
- 在生产环境中,可以通过静默模式(
debug_locks_silent
)记录锁错误,而不会干扰系统的正常运行。
- 在生产环境中,可以通过静默模式(
工作原理
1. 全局标志控制
debug_locks
:- 全局变量,初始值为
1
,表示锁调试功能启用。 - 当检测到锁错误时,可以通过
debug_locks_off()
将其设置为0
,关闭后续的调试功能。
- 全局变量,初始值为
debug_locks_silent
:- 全局变量,表示是否启用静默模式。如果启用,锁错误不会打印到控制台。
2. 锁调试关闭函数
static __always_inline int __debug_locks_off(void)
{return xchg(&debug_locks, 0);
}
- 使用
xchg
原子操作将debug_locks
设置为0
,确保在多线程环境中安全地关闭调试功能。 - 返回原来的值,用于判断调试功能是否已经关闭。
3. 锁错误检测
#define DEBUG_LOCKS_WARN_ON(c) \
({ \int __ret = 0; \\if (!oops_in_progress && unlikely(c)) { \instrumentation_begin(); \if (debug_locks_off() && !debug_locks_silent) \WARN(1, "DEBUG_LOCKS_WARN_ON(%s)", #c); \instrumentation_end(); \__ret = 1; \} \__ret; \
})
- 条件检测:
- 如果全局变量
oops_in_progress
为0
(表示当前没有内核错误正在处理),并且条件c
为真,则触发锁错误检测。
- 如果全局变量
- 关闭调试功能:
- 调用
debug_locks_off()
关闭调试功能,避免后续错误产生大量日志。
- 调用
- 打印警告:
- 如果未启用静默模式(
debug_locks_silent
为0
),通过WARN
宏打印锁错误信息。
- 如果未启用静默模式(
- 插桩支持:
- 使用
instrumentation_begin()
和instrumentation_end()
包裹调试代码,支持性能分析和跟踪。
- 使用
4. 锁调试关闭的通用函数
int debug_locks_off(void)
{if (debug_locks && __debug_locks_off()) {if (!debug_locks_silent) {console_verbose();return 1;}}return 0;
}
- 检查
debug_locks
是否启用,如果启用则关闭调试功能。 - 如果未启用静默模式,调用
console_verbose()
打印详细信息。
总结
debug_locks
是 Linux 内核中用于调试锁使用问题的重要工具,适用于开发、测试和生产环境。- 全局控制 和 静默模式 提供了灵活的调试选项,既可以捕获锁错误,又能避免过多的日志输出。
- 原子操作 和 插桩支持 确保了调试功能的安全性和性能。
- 通过
DEBUG_LOCKS_WARN_ON
等宏,可以快速检测锁的使用错误,并在必要时关闭调试功能,避免日志噪声。
lib/debug_locks.c
xchg
: xchg 的主要功能是以原子方式交换两个变量的值。原子操作意味着该操作在执行过程中不会被中断,因此在多线程环境中是线程安全的。
static __always_inline int __debug_locks_off(void)
{return xchg(&debug_locks, 0);
}
/** 我们希望通过一个全局标志一次性打开/关闭所有锁调试工具。* 原因在于,一旦发现并报告了一个bug,就可能会有一连串的后续bug,这只会把日志弄得一团糟。所以我们报了第一个,之后就闭嘴。*/
int debug_locks __read_mostly = 1;
EXPORT_SYMBOL_GPL(debug_locks);/** lock -testsuite使用<debug_locks_silent>来得到一个“静默失败”:当检测到锁定错误时,没有任何东西打印到控制台。*/
int debug_locks_silent __read_mostly;
EXPORT_SYMBOL_GPL(debug_locks_silent);/** Generic 'turn off all lock debugging' function:*/
int debug_locks_off(void)
{if (debug_locks && __debug_locks_off()) {if (!debug_locks_silent) {console_verbose();return 1;}}return 0;
}
EXPORT_SYMBOL_GPL(debug_locks_off);
include/linux/debug_locks.h
DEBUG_LOCKS_WARN_ON
#define DEBUG_LOCKS_WARN_ON(c) \
({ \int __ret = 0; \\if (!oops_in_progress //全局变量.用于指示当前是否正在处理内核 "oops"(内核错误)。&& unlikely(c)) { \instrumentation_begin(); \ //插桩开始if (debug_locks_off() && !debug_locks_silent) \WARN(1, "DEBUG_LOCKS_WARN_ON(%s)", #c); \instrumentation_end(); \ //插桩结束__ret = 1; \} \__ret; \
})