免费php网站模板,网站做配置文件的作用,手机网站绑定域名,wordpress怎么做404页面跳转lockdep是内核提供协助发现死锁问题的功能。
本文首先介绍何为lockdep#xff0c;然后如何在内核使能lockdep#xff0c;并简单分析内核lockdep相关代码。
最后构造不同死锁用例#xff0c;并分析如何根据lockdep输出发现问题根源。 Lockdep介绍
死锁是指两个或多个进程因…lockdep是内核提供协助发现死锁问题的功能。
本文首先介绍何为lockdep然后如何在内核使能lockdep并简单分析内核lockdep相关代码。
最后构造不同死锁用例并分析如何根据lockdep输出发现问题根源。 Lockdep介绍
死锁是指两个或多个进程因争夺资源而造成的互相等待的现象。 常见的死锁有如下两种 递归死锁中断等延迟操作中使用了锁和外面的锁构成了递归死锁。 AB-BA死锁多个锁因处理不当而引发死锁多个内核路径上的所处理顺序不一致也会导致死锁。 Linux内核提供死锁调试模块Lockdep跟踪每个锁的自身状态和各个锁之间的依赖关系经过一系列的验证规则来确保锁之间依赖关系是正确的。
使能Lockdep
Lockdep检测的锁包括spinlock、rwlock、mutex、rwsem的死锁锁的错误释放原子操作中睡眠等错误行为。 在内核中配置路径为Kernel hacking-Lock Debugging (spinlocks, mutexes, etc...)。 下面是lockcep内核选项及其解释
CONFIG_DEBUG_RT_MUTEXESy
检测rt mutex的死锁并自动报告死锁现场信息。
CONFIG_DEBUG_SPINLOCKy
检测spinlock的未初始化使用等问题。配合NMI watchdog使用能发现spinlock死锁。
CONFIG_DEBUG_MUTEXESy
检测并报告mutex错误
CONFIG_DEBUG_WW_MUTEX_SLOWPATHy
检测wait/wound类型mutex的slowpath测试。
CONFIG_DEBUG_LOCK_ALLOCy
检测使用中的锁(spinlock/rwlock/mutex/rwsem)被释放或者使用中的锁被重新初始化或者在进程退出时持有锁。
CONFIG_PROVE_LOCKINGy
使内核能在死锁发生前报告死锁详细信息。参见/proc/lockdep_chains。 Lock相关内核节点
/proc/sys/kernel/lock_stat------------------------置位则可以查看/proc/lock_stat统计信息清楚则关闭lockdep统计信息。 /proc/sys/kernel/max_lock_depth-------------- /proc/sys/kernel/prove_locking /proc/locks /proc/lock_stat-------------------------------------关于锁的使用统计信息 /proc/lockdep---------------------------------------存在依赖关系的锁 /proc/lockdep_stats------------------------------存在依赖关系锁的统计信息 /proc/lockdep_chains----------------------------依赖关系锁链表 内核还提供了了Tracepoint协助发现锁的使用问题/sys/kernel/debug/tracing/events/lock。 测试spin_lock死锁 构造测试用例代码如下 #include linux/init.h #include linux/module.h #include linux/kernel.h #include linux/spinlock.h
static DEFINE_SPINLOCK(hack_spinA); static DEFINE_SPINLOCK(hack_spinB);
void hack_spinAB(void) { printk(hack_lockdep: A-B\n); spin_lock(hack_spinA); spin_lock(hack_spinB); }
void hack_spinBA(void) { printk(hack_lockdep: B-A\n); spin_lock(hack_spinB); }
static int __init lockdep_test_init(void) { printk(figo: my lockdep module init); hack_spinAB(); hack_spinBA(); return 0; }
static void __exit lockdep_test_exit(void) { printk(goodbye\n); }
MODULE_LICENSE(GPL); //没有此句不然会造成内核污染在加载模块时死锁检测机制会被迫关闭Disabling lock debugging due to kernel taint module_init(lockdep_test_init); module_exit(lockdep_test_exit);
执行insmod data/lock.ko 后(检测发生死锁时报错)控制台显示如下。 首先从死锁描述大概可以知道死锁类型。 然后详细介绍了产生死锁的点这时就可以大概知道是哪个锁有哪些地方调用导致了死锁。 接着是详细的发生死锁的backtrace有助于分析死锁产生时的栈回溯。 figo: my lockdep module 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_init0x30/0x3c [lock] ------------lockdep_test_init中调用hack_spinBA再次持有hack_spinB锁 but task is already holding lock: (hack_spinB){....}, at: [bf000038] hack_spinAB0x38/0x3c [lock] -----------------hack_spinB已经在hack_spinAB函数中被持有 other info that might help us debug this: -----------------------------------------------------锁的其它补充信息 Possible unsafe locking scenario: CPU0 ---- lock(hack_spinB); lock(hack_spinB); *** DEADLOCK *** May be due to missing lock nesting notation 2 locks held by insmod/658: -------------------------------------------------------------------进程共持有两个锁 #0: (hack_spinA){....}, at: [bf000030] hack_spinAB0x30/0x3c [lock] #1: (hack_spinB){....}, at: [bf000038] hack_spinAB0x38/0x3c [lock] stack backtrace:------------------------------------------栈回溯信息可以看出从lockdep_test_init-_raw_spin_lock-lock_acquire的调用路径。 CPU: 0 PID: 658 Comm: insmod Tainted: G O 4.0.0 #87 Hardware name: ARM-Versatile Express [c00171b4] (unwind_backtrace) from [c0012e7c] (show_stack0x20/0x24) [c0012e7c] (show_stack) from [c05ade10] (dump_stack0x8c/0xb4) [c05ade10] (dump_stack) from [c006b988] (__lock_acquire0x1aa4/0x1f64) [c006b988] (__lock_acquire) from [c006c55c] (lock_acquire0xf4/0x190) [c006c55c] (lock_acquire) from [c05b4ec8] (_raw_spin_lock0x60/0x98) [c05b4ec8] (_raw_spin_lock) from [bf002030] (lockdep_test_init0x30/0x3c [lock]) [bf002030] (lockdep_test_init [lock]) from [c0008a28] (do_one_initcall0x9c/0x1e8) [c0008a28] (do_one_initcall) from [c05abf30] (do_init_module0x70/0x1c0) [c05abf30] (do_init_module) from [c00a4ddc] (load_module0x18b0/0x1f90) [c00a4ddc] (load_module) from [c00a55fc] (SyS_init_module0x140/0x150) [c00a55fc] (SyS_init_module) from [c000ec80] (ret_fast_syscall0x0/0x4c) INFO: rcu_sched self-detected stall on CPU 0: (2099 ticks this GP) idle5ed/140000000000001/0 softirq13024/13024 fqs1783 (t2100 jiffies g-51 c-52 q22) Task dump for CPU 0: insmod R running 0 658 657 0x00000002 [c00171b4] (unwind_backtrace) from [c0012e7c] (show_stack0x20/0x24) [c0012e7c] (show_stack) from [c0052874] (sched_show_task0x128/0x184) [c0052874] (sched_show_task) from [c0055dd0] (dump_cpu_task0x48/0x4c) [c0055dd0] (dump_cpu_task) from [c0082878] (rcu_dump_cpu_stacks0x9c/0xd4) [c0082878] (rcu_dump_cpu_stacks) from [c008665c] (rcu_check_callbacks0x640/0x968) [c008665c] (rcu_check_callbacks) from [c008b628] (update_process_times0x4c/0x74) [c008b628] (update_process_times) from [c009a1d4] (tick_periodic0x54/0xf8) [c009a1d4] (tick_periodic) from [c009a3d8] (tick_handle_periodic0x38/0x98) [c009a3d8] (tick_handle_periodic) from [c00164a4] (twd_handler0x40/0x50) [c00164a4] (twd_handler) from [c007dfc4] (handle_percpu_devid_irq0xd8/0x1dc) [c007dfc4] (handle_percpu_devid_irq) from [c0079a7c] (generic_handle_irq0x3c/0x4c) [c0079a7c] (generic_handle_irq) from [c0079dc4] (__handle_domain_irq0x6c/0xc4) [c0079dc4] (__handle_domain_irq) from [c0008740] (gic_handle_irq0x34/0x6c) [c0008740] (gic_handle_irq) from [c0013a44] (__irq_svc0x44/0x5c) Exception stack(0xed5c9d18 to 0xed5c9d60) 9d00: 00000000 00010000 9d20: 0000ffff c02f3898 bf0001b0 c0b1d248 123cc000 00000000 0c99b2c5 00000000 9d40: 00000000 ed5c9d84 ed5c9d60 ed5c9d60 c0070cb4 c0070cb4 60000013 ffffffff [c0013a44] (__irq_svc) from [c0070cb4] (do_raw_spin_lock0xf0/0x1e0) [c0070cb4] (do_raw_spin_lock) from [c05b4eec] (_raw_spin_lock0x84/0x98) [c05b4eec] (_raw_spin_lock) from [bf002030] (lockdep_test_init0x30/0x3c [lock]) [bf002030] (lockdep_test_init [lock]) from [c0008a28] (do_one_initcall0x9c/0x1e8) [c0008a28] (do_one_initcall) from [c05abf30] (do_init_module0x70/0x1c0) [c05abf30] (do_init_module) from [c00a4ddc] (load_module0x18b0/0x1f90) [c00a4ddc] (load_module) from [c00a55fc] (SyS_init_module0x140/0x150) [c00a55fc] (SyS_init_module) from [c000ec80] (ret_fast_syscall0x0/0x4c) BUG: spinlock lockup suspected on CPU#0, insmod/658-----------------------------------------错误类型是spinlock下面的backtrace和上面基本一致。 lock: hack_spinB0x0/0xfffffedc [lock], .magic: dead4ead, .owner: insmod/658, .owner_cpu: 0-----------发生死锁的是hack_spinB CPU: 0 PID: 658 Comm: insmod Tainted: G O 4.0.0 #87 Hardware name: ARM-Versatile Express [c00171b4] (unwind_backtrace) from [c0012e7c] (show_stack0x20/0x24) [c0012e7c] (show_stack) from [c05ade10] (dump_stack0x8c/0xb4) [c05ade10] (dump_stack) from [c0070b2c] (spin_dump0x8c/0xd0) [c0070b2c] (spin_dump) from [c0070cd0] (do_raw_spin_lock0x10c/0x1e0) [c0070cd0] (do_raw_spin_lock) from [c05b4eec] (_raw_spin_lock0x84/0x98) [c05b4eec] (_raw_spin_lock) from [bf002030] (lockdep_test_init0x30/0x3c [lock]) [bf002030] (lockdep_test_init [lock]) from [c0008a28] (do_one_initcall0x9c/0x1e8) [c0008a28] (do_one_initcall) from [c05abf30] (do_init_module0x70/0x1c0) [c05abf30] (do_init_module) from [c00a4ddc] (load_module0x18b0/0x1f90) [c00a4ddc] (load_module) from [c00a55fc] (SyS_init_module0x140/0x150) [c00a55fc] (SyS_init_module) from [c000ec80] (ret_fast_syscall0x0/0x4c)
CONFIG_LOCKDEPy
整个Lockdep的总开关。参见/proc/lockdep、/proc/lockdep_stats。
CONFIG_LOCK_STATy
记锁持有竞争区域的信息包括等待时间、持有时间等等信息。参见/proc/lock_stat。
CONFIG_DEBUG_LOCKDEPy
会对Lockdep的使用过程中进行更多的自我检测会增加很多额外开销。
CONFIG_DEBUG_ATOMIC_SLEEPy
在atomic section中睡眠可能造成很多不可预测的问题这些atomic section包括spinlock持锁、rcu读操作、禁止内核抢占部分、中断处理中等等。