本文来源:
https://www.cnblogs.com/arnoldlu/p/8580387.html
关键词:LockDep、spinlock、mutex 。
lockdep是内核提供协助发现死锁问题的功能 。
本文首先介绍何为lockdep,然后如何在内核使能lockdep,并简单分析内核lockdep相关代码 。
最后构造不同死锁用例,并分析如何根据lockdep输出发现问题根源 。
1. Lockdep介绍死锁是指两个或多个进程因争夺资源而造成的互相等待的现象 。
常见的死锁有如下两种:
递归死锁:中断等延迟操作中使用了锁,和外面的锁构成了递归死锁 。
AB-BA死锁:多个锁因处理不当而引发死锁,多个内核路径上的所处理顺序不一致也会导致死锁 。
linux内核提供死锁调试模块Lockdep,跟踪每个锁的自身状态和各个锁之间的依赖关系,经过一系列的验证规则来确保锁之间依赖关系是正确的 。
2. 内核死锁检测Lockdep2.1 使能LockdepLockdep检测的锁包括spinlock、rwlock、mutex、rwsem的死锁,锁的错误释放,原子操作中睡眠等错误行为 。
在内核中配置路径为:Kernel hacking->Lock Debugging (spinlocks, mutexes, etc...) 。
文章插图
下面是lockcep内核选项及其解释:
CONFIG_DEBUG_RT_MUTEXES=y
检测rt mutex的死锁,并自动报告死锁现场信息 。
CONFIG_DEBUG_SPINLOCK=y
检测spinlock的未初始化使用等问题 。配合NMI watchdog使用,能发现spinlock死锁 。
CONFIG_DEBUG_MUTEXES=y
检测并报告mutex错误
CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
检测wait/wound类型mutex的slowpath测试 。
CONFIG_DEBUG_LOCK_ALLOC=y
检测使用中的锁(spinlock/rwlock/mutex/rwsem)被释放,或者使用中的锁被重新初始化,或者在进程退出时持有锁 。
CONFIG_PROVE_LOCKING=y
使内核能在死锁发生前报告死锁详细信息 。参见/proc/lockdep_chains 。
CONFIG_LOCKDEP=y
整个Lockdep的总开关 。参见/proc/lockdep、/proc/lockdep_stats 。
CONFIG_LOCK_STAT=y
记锁持有竞争区域的信息,包括等待时间、持有时间等等信息 。参见/proc/lock_stat 。
CONFIG_DEBUG_LOCKDEP=y
会对Lockdep的使用过程中进行更多的自我检测,会增加很多额外开销 。
CONFIG_DEBUG_ATOMIC_SLEEP=y
在atomic section中睡眠可能造成很多不可预测的问题,这些atomic section包括spinlock持锁、rcu读操作、禁止内核抢占部分、中断处理中等等 。
2.2 Lock相关内核节点
/proc/sys/kernel/lock_stat------------------------置位则可以查看/proc/lock_stat统计信息,清楚则关闭lockdep统计信息 。内核还提供了了Tracepoint协助发现锁的使用问题:/sys/kernel/debug/tracing/events/lock 。
/proc/sys/kernel/max_lock_depth--------------
/proc/sys/kernel/prove_locking
/proc/locks
/proc/lock_stat-------------------------------------关于锁的使用统计信息
/proc/lockdep---------------------------------------存在依赖关系的锁
/proc/lockdep_stats------------------------------存在依赖关系锁的统计信息
/proc/lockdep_chains----------------------------依赖关系锁链表
2.3 lockdep代码简单分析3. Lockdep测试3.1 测试spin_lock死锁构造测试用例代码如下:
void hack_spinAB(void){printk("hack_lockdep:A->Bn");spin_lock(&hack_spinA);spin_lock(&hack_spinB);}void hack_spinBA(void){printk("hack_lockdep:B->An");spin_lock(&hack_spinB);}static int __init lockdep_test_init(void){printk("al: lockdep error test initn");hack_spinAB;hack_spinBA;return 0;}执行insmod data/lock.ko 后,控制台显示如下 。
【Linux死锁检测-Lockdep】首先从死锁描述大概可以知道死锁类型 。
然后详细介绍了产生死锁的点,这时就可以大概知道是哪个锁,有哪些地方调用导致了死锁 。
接着是详细的发生死锁的backtrace,有助于分析死锁产生时的栈回溯 。
al: lockdep error test init
hack_lockdep:A->B
hack_lockdep:B->A
=============================================
[ INFO: possible recursive locking detected ]---------------------------------------------------------------检测到的死锁描述:递归死锁类型
4.0.0+ #87 Tainted: G O
---------------------------------------------
insmod/658 is trying to acquire lock:---------------------------------------------------------------------------死锁细节描述:欲持锁点和已持锁点
(hack_spinB){+.+...}, at: [<bf002030>] lockdep_test_init+0x30/0x3c [lock]--------------------------lockdep_test_init中调用hack_spinBA再次持有hack_spinB锁
推荐阅读
- 11个审查Linux是否被入侵的方法
- 十大企业级Linux服务器安全防护要点
- Linux 下你所不知道的 7 个 SSH 命令用法
- Linux系统安全Centos 7的Firewalld防火墙基础
- linux定时任务,让你更深入的了解系统
- 聊聊关于Linux的登录脚本和登出脚本
- Linux怎么复制文件到其他文件夹
- Linux运维:反斜杠与反引号的使用
- 怎么用Linux命令行测试网站连接速度
- 如何使用linux脚本监控Tomcat服务器是否宕机和宕机后自动重启