一、简介
lockdep 是用于检测和分析内核中的锁相关问题的工具,它有助于发现潜在的死锁和竞争条件。在多核系统中,锁是用来同步多个执行线程(或进程)的访问共享资源的机制。由于多核环境下的并发访问,锁的正确使用变得尤为重要。
下面是关于 lockdep 的一些重要信息:
目的:lockdep 旨在帮助内核开发者和调试人员找到潜在的锁相关问题,特别是死锁和竞争条件。
工作原理:lockdep 通过跟踪内核中的锁和锁的获取情况,建立锁之间的依赖关系图。然后,它使用图论算法来检测潜在的锁依赖循环,从而发现可能的死锁情况。
依赖关系图:lockdep 创建一个依赖关系图,记录锁的层次结构和它们之间的依赖关系。当一个线程尝试获取一个锁时,lockdep 会检查是否存在潜在的循环依赖,如果有,就可能会导致死锁。
使用方法:要启用 lockdep,需要在内核编译配置中开启相应的选项。然后,通过在内核启动参数中加入
lockdep=1
来启用 lockdep 机制。在运行时,lockdep 会在检测到潜在问题时输出相应的警告信息。警告信息:当 lockdep 检测到可能的锁问题时,它会打印出相关的警告信息,其中包含了问题的描述,涉及的锁,以及可能导致问题的代码路径。
调试:使用 lockdep 并不意味着一定存在问题,有时它可能会给出误报。因此,对于 lockdep 输出的警告信息,开发者需要进一步进行调查和分析,确认是否真的存在问题。
性能影响:lockdep 在运行时会对性能产生一定影响,因为它需要跟踪锁的获取和释放情况并维护依赖关系图。因此,在生产环境中通常不会一直启用 lockdep,而是在需要进行调试和故障排除时启用。
二、内核配置选项
Kernel hacking->Lock Debugging (spinlocks, mutexes, etc...)
Lock debugging: prove locking correctness
启用此选项后,内核会在运行时进行锁验证,检查锁的正确使用情况,以防止潜在的死锁和竞争条件。
CONFIG_PROVE_LOCKING:
This feature enables the kernel to prove that all locking
that occurs in the kernel runtime is mathematically
correct: that under no circumstance could an arbitrary (and
not yet triggered) combination of observed locking
sequences (on an arbitrary number of CPUs, running an
arbitrary number of tasks and interrupt contexts) cause a
deadlock. |
In short, this feature enables the kernel to report locking
related deadlocks before they actually occur.
The proof does not depend on how hard and complex a
deadlock scenario would be to trigger: how many
participant CPUs, tasks and irq-contexts would be needed
for it to trigger. The proof also does not depend on
timing: if a race and a resulting deadlock is possible
theoretically (no matter how unlikely the race scenario
is), it will be proven so and will immediately be
reported by the kernel (once the event is observed that
makes the deadlock theoretically possible).
If a deadlock is impossible (i.e. the locking rules, as
observed by the kernel, are mathematically correct), the
kernel reports nothing.
NOTE:thisfeaturecanalsobeenabledforrwlocks,mutexes
andrwsems-inwhichcasealldependenciesbetweenthese
differentlockingvariantsareobservedandmappedtoo,and
theproofofobservedcorrectnessisalsomaintainedforan
arbitrarycombinationoftheseseparatelockingvariants.
Formoredetails,seeDocumentation/locking/lockdep-design.rst.
Symbol:PROVE_LOCKING[=n]
Type:bool
Definedatlib/Kconfig.debug:1192
Prompt:Lockdebugging:provelockingcorrectness
Dependson:DEBUG_KERNEL[=y]&&LOCK_DEBUGGING_SUPPORT[=y]
Location:
->Kernelhacking
->LockDebugging(spinlocks,mutexes,etc...)
Selects:LOCKDEP[=n]&&DEBUG_SPINLOCK[=n]&&DEBUG_MUTEXES[=n]&&DEBUG_RT_MUTEXES[=n]&&DEBUG_RWSEMS[=n]&&DEBUG_WW_MUTEX_SLOWPATH[=n]&&\
DEBUG_LOCK_ALLOC[=n]&&PREEMPT_COUNT[=n]&&TRACE_IRQFLAGS[=n]
Lock usage statistics
启用此选项后,内核会收集有关锁的统计信息,包括锁的使用次数、等待次数等。这些统计信息对于锁的性能分析非常有用。
CONFIG_LOCK_STAT:
This feature enables tracking lock contention points
For more details, see Documentation/locking/lockstat.rst
This also enables lock events required by "perf lock",
subcommand of perf.
If you want to use "perf lock", you also need to turn on
CONFIG_EVENT_TRACING.
CONFIG_LOCK_STAT defines "contended" and "acquired" lock events.
(CONFIG_LOCKDEP defines "acquire" and "release" events.)
Symbol: LOCK_STAT [=n]
Type : bool
Defined at lib/Kconfig.debug:1256
Prompt: Lock usage statistics
Depends on: DEBUG_KERNEL [=y] && LOCK_DEBUGGING_SUPPORT [=y]
Location:
-> Kernel hacking
-> Lock Debugging (spinlocks, mutexes, etc...)
Selects: LOCKDEP [=n] && DEBUG_SPINLOCK [=n] && DEBUG_MUTEXES [=n] && DEBUG_RT_MUTEXES [=n] && DEBUG_LOCK_ALLOC [=n]
RT Mutex debugging, deadlock detection
启用此选项后,内核会对实时互斥量(rtmutex)进行调试和验证。rtmutex 是 Linux 内核中用于实时任务的一种特殊互斥量。
CONFIG_DEBUG_RT_MUTEXES:
This allows rt mutex semantics violations and rt mutex related
deadlocks (lockups) to be detected and reported automatically.
Symbol: DEBUG_RT_MUTEXES [=n]
Type : bool
Defined at lib/Kconfig.debug:1278
Prompt: RT Mutex debugging, deadlock detection
Depends on: DEBUG_KERNEL [=y] && RT_MUTEXES [=y]
Location:
-> Kernel hacking
-> Lock Debugging (spinlocks, mutexes, etc...)
Selected by [n]:
- PROVE_LOCKING [=n] && DEBUG_KERNEL [=y] && LOCK_DEBUGGING_SUPPORT [=y] && RT_MUTEXES [=y]
- LOCK_STAT [=n] && DEBUG_KERNEL [=y] && LOCK_DEBUGGING_SUPPORT [=y] && RT_MUTEXES [=y]
- DEBUG_LOCK_ALLOC [=n] && DEBUG_KERNEL [=y] && LOCK_DEBUGGING_SUPPORT [=y] && RT_MUTEXES [=y]
Spinlock and rw-lock debugging: basic checks
启用此选项后,内核会对自旋锁进行调试和验证。自旋锁是一种在多核系统中用于短暂等待的锁。
CONFIG_DEBUG_SPINLOCK:
Say Y here and build SMP to catch missing spinlock initialization
and certain other kinds of spinlock errors commonly made. This is
best used in conjunction with the NMI watchdog so that spinlock
deadlocks are also debuggable.
Symbol: DEBUG_SPINLOCK [=n]
Type : bool
Defined at lib/Kconfig.debug:1285
Prompt: Spinlock and rw-lock debugging: basic checks
Depends on: DEBUG_KERNEL [=y]
Location:
-> Kernel hacking
-> Lock Debugging (spinlocks, mutexes, etc...)
Selects: UNINLINE_SPIN_UNLOCK [=n]
Selected by [n]:
- PROVE_LOCKING [=n] && DEBUG_KERNEL [=y] && LOCK_DEBUGGING_SUPPORT [=y]
- LOCK_STAT [=n] && DEBUG_KERNEL [=y] && LOCK_DEBUGGING_SUPPORT [=y]
- DEBUG_WW_MUTEX_SLOWPATH [=n] && DEBUG_KERNEL [=y] && LOCK_DEBUGGING_SUPPORT [=y]
- DEBUG_LOCK_ALLOC [=n] && DEBUG_KERNEL [=y] && LOCK_DEBUGGING_SUPPORT [=y]
Mutex debugging: basic checks
启用此选项后,内核会对互斥量进行调试和验证。互斥量是一种用于控制共享资源访问的常见锁机制。
CONFIG_DEBUG_MUTEXES:
This feature allows mutex semantics violations to be detected and
reported.
Symbol: DEBUG_MUTEXES [=n]
Type : bool
Defined at lib/Kconfig.debug:1295
Prompt: Mutex debugging: basic checks
Depends on: DEBUG_KERNEL [=y]
Location:
-> Kernel hacking
-> Lock Debugging (spinlocks, mutexes, etc...)
Selected by [n]:
- PROVE_LOCKING [=n] && DEBUG_KERNEL [=y] && LOCK_DEBUGGING_SUPPORT [=y]
- LOCK_STAT [=n] && DEBUG_KERNEL [=y] && LOCK_DEBUGGING_SUPPORT [=y]
- DEBUG_WW_MUTEX_SLOWPATH [=n] && DEBUG_KERNEL [=y] && LOCK_DEBUGGING_SUPPORT [=y]
- DEBUG_LOCK_ALLOC [=n] && DEBUG_KERNEL [=y] && LOCK_DEBUGGING_SUPPORT [=y]
Wait/wound mutex debugging: Slowpath testing
启用此选项后,内核会对内核中的“等待约束”(Wait-While-Condition)互斥量进行调试和验证。这种互斥量用于等待特定条件的发生。
CONFIG_DEBUG_WW_MUTEX_SLOWPATH:
This feature enables slowpath testing for w/w mutex users by
injecting additional -EDEADLK wound/backoff cases. Together with
the full mutex checks enabled with (CONFIG_PROVE_LOCKING) this
will test all possible w/w mutex interface abuse with the
exception of simply not acquiring all the required locks.
Note that this feature can introduce significant overhead, so
it really should not be enabled in a production or distro kernel,
even a debug kernel. If you are a driver writer, enable it. If
you are a distro, do not.
Symbol: DEBUG_WW_MUTEX_SLOWPATH [=n]
Type : bool
Defined at lib/Kconfig.debug:1302
Prompt: Wait/wound mutex debugging: Slowpath testing
Depends on: DEBUG_KERNEL [=y] && LOCK_DEBUGGING_SUPPORT [=y]
Location:
-> Kernel hacking
-> Lock Debugging (spinlocks, mutexes, etc...)
Selects: DEBUG_LOCK_ALLOC [=n] && DEBUG_SPINLOCK [=n] && DEBUG_MUTEXES [=n]
Selected by [n]:
- PROVE_LOCKING [=n] && DEBUG_KERNEL [=y] && LOCK_DEBUGGING_SUPPORT [=y]
RW Semaphore debugging: basic checks (NEW)
启用此选项后,内核会对读写信号量(rwsem)进行调试和验证。rwsem 是内核中实现读写锁的机制。
CONFIG_DEBUG_RWSEMS:
This debugging feature allows mismatched rw semaphore locks
and unlocks to be detected and reported.
Symbol: DEBUG_RWSEMS [=n]
Type : bool
Defined at lib/Kconfig.debug:1319
Prompt: RW Semaphore debugging: basic checks
Depends on: DEBUG_KERNEL [=y]
Location:
-> Kernel hacking
-> Lock Debugging (spinlocks, mutexes, etc...)
Selected by [n]:
- PROVE_LOCKING [=n] && DEBUG_KERNEL [=y] && LOCK_DEBUGGING_SUPPORT [=y]
Lock debugging: detect incorrect freeing of live locks
启用此选项后,内核会提供更详细的锁分配和释放跟踪信息,有助于调试和分析锁的分配情况。
CONFIG_DEBUG_LOCK_ALLOC:
This feature will check whether any held lock (spinlock, rwlock,
mutex or rwsem) is incorrectly freed by the kernel, via any of the
memory-freeing routines (kfree(), kmem_cache_free(), free_pages(),
vfree(), etc.), whether a live lock is incorrectly reinitialized via
spin_lock_init()/mutex_init()/etc., or whether there is any lock
held during task exit.
Symbol: DEBUG_LOCK_ALLOC [=n]
Type : bool
Defined at lib/Kconfig.debug:1326
Prompt: Lock debugging: detect incorrect freeing of live locks
Depends on: DEBUG_KERNEL [=y] && LOCK_DEBUGGING_SUPPORT [=y]
Location:
-> Kernel hacking
-> Lock Debugging (spinlocks, mutexes, etc...)
Selects: DEBUG_SPINLOCK [=n] && DEBUG_MUTEXES [=n] && DEBUG_RT_MUTEXES [=n] && LOCKDEP [=n]
Selected by [n]:
- PROVE_LOCKING [=n] && DEBUG_KERNEL [=y] && LOCK_DEBUGGING_SUPPORT [=y]
- LOCK_STAT [=n] && DEBUG_KERNEL [=y] && LOCK_DEBUGGING_SUPPORT [=y]
- DEBUG_WW_MUTEX_SLOWPATH [=n] && DEBUG_KERNEL [=y] && LOCK_DEBUGGING_SUPPORT [=y]
Sleep inside atomic section checking
启用此选项后,内核会对原子睡眠进行调试和验证。原子睡眠是一种轻量级的等待机制。
CONFIG_DEBUG_ATOMIC_SLEEP:
If you say Y here, various routines which may sleep will become very
noisy if they are called inside atomic sections: when a spinlock is
held, inside an rcu read side critical section, inside preempt disabled
sections, inside an interrupt, etc...
Symbol: DEBUG_ATOMIC_SLEEP [=n]
Type : bool
Defined at lib/Kconfig.debug:1359
Prompt: Sleep inside atomic section checking
Depends on: DEBUG_KERNEL [=y] && !ARCH_NO_PREEMPT [=n]
Location:
-> Kernel hacking
-> Lock Debugging (spinlocks, mutexes, etc...)
Selects: PREEMPT_COUNT [=n]
Locking API boot-time self-tests
启用此选项后,内核会运行锁相关的自检测试,以确保锁的API正常工作。
CONFIG_DEBUG_LOCKING_API_SELFTESTS:
Say Y here if you want the kernel to run a short self-test during
bootup. The self-test checks whether common types of locking bugs
are detected by debugging mechanisms or not. (if you disable
lock debugging then those bugs wont be detected of course.)
The following locking APIs are covered: spinlocks, rwlocks,
mutexes and rwsems.
Symbol: DEBUG_LOCKING_API_SELFTESTS [=n]
Type : bool
Defined at lib/Kconfig.debug:1370
Prompt: Locking API boot-time self-tests
Depends on: DEBUG_KERNEL [=y] && !PREEMPT_RT [=n]
Location:
-> Kernel hacking
-> Lock Debugging (spinlocks, mutexes, etc...)
torture tests for locking
启用此选项后,内核会运行锁压力测试,用于测试锁的性能和稳定性。
CONFIG_LOCK_TORTURE_TEST:
This option provides a kernel module that runs torture tests
on kernel locking primitives. The kernel module may be built
after the fact on the running kernel to be tested, if desired.
Say Y here if you want kernel locking-primitive torture tests
to be built into the kernel.
Say M if you want these torture tests to build as a module.
Say N if you are unsure.
Symbol: LOCK_TORTURE_TEST [=n]
Type : tristate
Defined at lib/Kconfig.debug:1381
Prompt: torture tests for locking
Depends on: DEBUG_KERNEL [=y]
Location:
-> Kernel hacking
-> Lock Debugging (spinlocks, mutexes, etc...)
Selects: TORTURE_TEST [=n]
Wait/wound mutex selftests
启用此选项后,内核会运行“等待约束”互斥量的自检测试。
CONFIG_WW_MUTEX_SELFTEST:
This option provides a kernel module that runs tests on the
on the struct ww_mutex locking API.
It is recommended to enable DEBUG_WW_MUTEX_SLOWPATH in conjunction
with this test harness.
Say M if you want these self tests to build as a module.
Say N if you are unsure.
Symbol: WW_MUTEX_SELFTEST [=n]
Type : tristate
Defined at lib/Kconfig.debug:1395
Prompt: Wait/wound mutex selftests
Location:
-> Kernel hacking
-> Lock Debugging (spinlocks, mutexes, etc...)
torture tests for smp_call_function*() (NEW)
启用此选项后,内核会运行 SLAB/SLUB/SLUB3 分配器的压力测试。
CONFIG_SCF_TORTURE_TEST:
This option provides a kernel module that runs torture tests
on the smp_call_function() family of primitives. The kernel
module may be built after the fact on the running kernel to
be tested, if desired.
Symbol: SCF_TORTURE_TEST [=n]
Type : tristate
Defined at lib/Kconfig.debug:1407
Prompt: torture tests for smp_call_function*()
Depends on: DEBUG_KERNEL [=y]
Location:
-> Kernel hacking
-> Lock Debugging (spinlocks, mutexes, etc...)
Selects: TORTURE_TEST [=n]
Debugging for csd_lock_wait(), called from smp_call_function*() (NEW)
启用此选项后,内核会提供更详细的等待锁调试信息,用于分析等待锁的情况。
CONFIG_CSD_LOCK_WAIT_DEBUG:
|
| This option enables debug prints when CPUs are slow to respond
| to the smp_call_function*() IPI wrappers. These debug prints
| include the IPI handler function currently executing (if any)
| and relevant stack traces.
|
| Symbol: CSD_LOCK_WAIT_DEBUG [=n]
| Type : bool
| Defined at lib/Kconfig.debug:1417
| Prompt: Debugging for csd_lock_wait(), called from smp_call_function*()
| Depends on: DEBUG_KERNEL [=y] && 64BIT [=y]
| Location:
| -> Kernel hacking
| -> Lock Debugging (spinlocks, mutexes, etc...)
三、配置实践
配置选项
+CONFIG_PROVE_LOCKING=y
+CONFIG_DEBUG_LOCK_ALLOC=y
+CONFIG_DEBUG_LOCKDEP=y
+CONFIG_LOCK_STAT=y
+CONFIG_DEBUG_LOCKING_API_SELFTESTS=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
+CONFIG_LOCKDEP=y
死锁现象
构造锁问题,运行测试程序,报错如下信息:
[ 201.324117]
[ 201.324120] ============================================
[ 201.324122] WARNING: possible recursive locking detected
[ 201.324126] 5.10.59-rt52-gaaf3c1a02253-dirty #4 Tainted: G O
[ 201.324130] --------------------------------------------
[ 201.324132] vio_gw3/1810 is trying to acquire lock:
[ 201.324136] ffff00018b0a15b8 (&this->raw_slock){....}-{2:2}, at: vio_frame_done+0x38/0x290 [test_vio_common]
[ 201.324184]
[ 201.324184] but task is already holding lock:
[ 201.324186] ffff00018b0a1a58 (&this->raw_slock){....}-{2:2}, at: test_ynr_fe_work+0x1ec/0x370 [test_ynr]
[ 201.324222]
[ 201.324222] other info that might help us debug this:
[ 201.324225] Possible unsafe locking scenario:
[ 201.324225]
[ 201.324227] CPU0
[ 201.324228] ----
[ 201.324230] lock(&this->raw_slock);
[ 201.324235] lock(&this->raw_slock);
[ 201.324240]
[ 201.324240] *** DEADLOCK ***
[ 201.324240]
[ 201.324242] May be due to missing lock nesting notation
[ 201.324242]
[ 201.324244] 3 locks held by vio_gw3/1810:
[ 201.324248] #0: ffff00018b0a1a58 (&this->raw_slock){....}-{2:2}, at: test_ynr_fe_work+0x1ec/0x370 [test_ynr]
[ 201.324278] #1: ffff00018b0a01c0 (&ynr->shared_slock){+.+.}-{0:0}, at: test_ynr_fe_work+0x224/0x370 [test_ynr]
[ 201.324307] #2: ffff800012286ca0 (rcu_read_lock){....}-{1:2}, at: rt_spin_lock+0x30/0xe0
[ 201.324329]
[ 201.324329] stack backtrace:
[ 201.324332] CPU: 4 PID: 1810 Comm: vio_gw3 Tainted: G O 5.10.59-rt52-gaaf3c1a02253-dirty #4
[ 201.324339] Hardware name: Horizon Robotics Journey 5 DVB (DT)
[ 201.324343] Call trace:
[ 201.324345] dump_backtrace+0x0/0x1d0
[ 201.324355] show_stack+0x14/0x20
[ 201.324362] dump_stack+0xf4/0x160
[ 201.324369] __lock_acquire+0x17f4/0x18b8
[ 201.324377] lock_acquire+0x280/0x438
[ 201.324383] _raw_spin_lock_irqsave+0x84/0x190
[ 201.324390] vio_frame_done+0x38/0x290 [test_vio_common]
[ 201.324417] test_ynr_fe_work+0x22c/0x370 [test_ynr]
[ 201.324438] test_ynr_handle_interrupt+0x2d0/0x2f8 [test_ynr]
[ 201.324458] test_ynr_frame_work+0x1dc/0x248 [test_ynr]
[ 201.324477] frame_work_function+0xbc/0x230 [test_vio_common]
[ 201.324504] kthread_worker_fn+0xcc/0x178
[ 201.324513] kthread+0x168/0x190
[ 201.324519] ret_from_fork+0x10/0x18
[ 201.514292] mcore found ce 598
[ 201.516787] [A][time_3: 1690352015 s, 514741 us] A: mback_msg: 146-1-3 598
[ 201.520678] remoteproc_trigger_backtrace
[ 201.520685] NMI backtrace for cpu 6
锁未初始化
构造未初始化锁,及使用了锁的异常。
[ 245.449775] INFO: trying to register non-static key.
[ 245.449778] The code is fine but needs lockdep annotation, or maybe
[ 245.449780] you didn't initialize this object before use?
[ 245.449782] turning off the locking correctness validator.
[ 245.449787] CPU: 7 PID: 1849 Comm: vio_gw3 Tainted: G O 5.10.59-rt52-gaaf3c1a02253-dirty #2
[ 245.449794] Hardware name: Horizon Robotics Journey 5 DVB (DT)
[ 245.449798] Call trace:
[ 245.449800] dump_backtrace+0x0/0x1d0
[ 245.449815] show_stack+0x14/0x20
[ 245.449822] dump_stack+0xf4/0x160
[ 245.449831] register_lock_class+0x47c/0x488
[ 245.449839] __lock_acquire+0x78/0x18b8
[ 245.449846] lock_acquire+0x280/0x438
[ 245.449852] rt_spin_lock+0x48/0xe0
[ 245.449859] test_ynr_fs_work+0x34/0x190 [test_ynr]
[ 245.449920] test_ynr_handle_interrupt+0x290/0x2f8 [test_ynr]
[ 245.449939] test_ynr_frame_work+0x1c8/0x248 [test_ynr]
[ 245.449958] frame_work_function+0xbc/0x230 [test_vio_common]
[ 245.449989] kthread_worker_fn+0xcc/0x178
[ 245.449998] kthread+0x168/0x190
[ 245.450004] ret_from_fork+0x10/0x18
需要注意的是:Lockdep 只会检测并report 第一次出错的地方,后面的一次锁问题就不再上报。
四、lockdep的proc
根据kernel/kernel/locking/lockdep_proc文件得知:
lockdep
功能:此文件用于查看内核中各种锁的统计信息。
使用方法:可以通过 cat 命令或其他文件查看工具来读取该文件的内容。
输出内容:该文件的输出包含多行,每一行描述一种类型的锁及其相关统计信息,如锁的名称、获取次数、等待次数等。
cat /proc/lockdep
.........................................................................
0000000052d34abd OPS: 12 FD: 14 BD: 3 +.+.: &share_hd->share_hd_lock
-> [00000000574f79f8] &lock->wait_lock
.........................................................................
0000000052d34abd OPS: 12 FD: 14 BD: 3 +.+.: &share_hd->share_hd_lock
0000000052d34abd
是锁的标识符,通常是锁的地址,用于唯一标识这个锁。OPS: 12
表示这个锁已经被获取的次数。FD: 14
表示等待这个锁的次数。BD: 3
表示这个锁存在的依赖关系的数量。+.+.
表示这个锁是有死锁风险的,lockdep 检测到这个锁可能导致死锁或竞争条件。第一个字符:
"+" 表示锁存在死锁风险。
"." 表示锁没有死锁风险。
第二个字符:
"+" 表示锁存在潜在的问题,但风险相对较低。
"." 表示锁没有潜在问题。
第三个字符:
"+" 表示锁存在更严重的潜在问题。
"." 表示锁没有更严重的潜在问题。
第四个字符:
"+" 表示锁存在更高级别的潜在问题,有很高的死锁风险。
"." 表示锁没有更高级别的潜在问题。
-> [00000000574f79f8] &lock->wait_lock
->
表示这是一个锁依赖关系,前面的锁依赖于后面的锁。[00000000574f79f8]
是另一个锁的标识符,通常是锁的地址,这个锁被称为&lock->wait_lock
。&lock->wait_lock
是锁的名称,通常是内核中的某个结构体成员的锁。
lockdep_stats
功能:此文件用于查看内核中各种锁的统计信息。
使用方法:可以通过 cat 命令或其他文件查看工具来读取该文件的内容。
输出内容:该文件的输出包含多行,每一行描述一种类型的锁及其相关统计信息,如锁的名称、获取次数、等待次数等。
cat /proc/lockdep_stats
lock-classes: 1459 [max: 8192]
direct dependencies: 11564 [max: 32768]
indirect dependencies: 58052
all direct dependencies: 64876
dependency chains: 18571 [max: 65536]
dependency chain hlocks used: 80954 [max: 327680]
dependency chain hlocks lost: 0
in-hardirq chains: 26
in-softirq chains: 0
in-process chains: 18545
stack-trace entries: 140629 [max: 524288]
number of stack traces: 6884
number of stack hash chains: 5629
combined max dependencies: 500742
hardirq-safe locks: 28
hardirq-unsafe locks: 952
softirq-safe locks: 0
softirq-unsafe locks: 873
irq-safe locks: 28
irq-unsafe locks: 952
hardirq-read-safe locks: 1
hardirq-read-unsafe locks: 97
softirq-read-safe locks: 0
softirq-read-unsafe locks: 93
irq-read-safe locks: 1
irq-read-unsafe locks: 97
uncategorized locks: 421
unused locks: 0
max locking depth: 19
max bfs queue depth: 581
chain lookup misses: 18695
chain lookup hits: 13102469
cyclic checks: 17833
redundant checks: 0
redundant links: 0
find-mask forwards checks: 1962
find-mask backwards checks: 2025
hardirq on events: 9076440
hardirq off events: 9076432
redundant hardirq ons: 346
redundant hardirq offs: 196734
softirq on events: 97064
softirq off events: 97064
redundant softirq ons: 0
redundant softirq offs: 0
debug_locks: 0
zapped classes: 5
zapped lock chains: 5
large chain blocks: 1
lock-classes: 1459 [max: 8192]:
表示当前内核中已识别的锁类别数为 1459,最大允许的锁类别数为 8192。
direct dependencies: 11564 [max: 32768]:
表示直接依赖关系的数量为 11564,最大允许的直接依赖关系数量为 32768。直接依赖关系是指锁之间直接的依赖关系。
indirect dependencies: 58052:
表示间接依赖关系的数量为 58052。间接依赖关系是指通过一系列锁依赖关系连接起来的锁之间的关系。
all direct dependencies: 64876:
表示所有直接依赖关系的数量,包括 direct dependencies 和 indirect dependencies。
dependency chains: 18571 [max: 65536]:
表示锁依赖关系链的数量为 18571,最大允许的锁依赖关系链数量为 65536。锁依赖关系链是指一组锁之间相互依赖的关系。
dependency chain hlocks used: 80954 [max: 327680]:
表示在锁依赖关系链中使用的硬件锁的数量为 80954,最大允许的硬件锁数量为 327680。
dependency chain hlocks lost: 0:
表示在锁依赖关系链中丢失的硬件锁的数量为 0。
in-hardirq chains: 26:
表示在硬中断处理期间使用的锁依赖关系链的数量为 26。
in-softirq chains: 0:
表示在软中断处理期间使用的锁依赖关系链的数量为 0。
in-process chains: 18545:
表示在进程上下文中使用的锁依赖关系链的数量为 18545。
stack-trace entries: 140629 [max: 524288]:
表示堆栈跟踪条目的数量为 140629,最大允许的堆栈跟踪条目数量为 524288。
number of stack traces: 6884:
表示使用的堆栈跟踪的数量为 6884。
number of stack hash chains: 5629:
表示堆栈哈希链的数量为 5629。
combined max dependencies: 500742:
表示最大允许的组合锁依赖关系数为 500742。
hardirq-safe locks: 28:
表示硬中断安全的锁的数量为 28。
hardirq-unsafe locks: 952:
表示硬中断不安全的锁的数量为 952。
softirq-safe locks: 0:
表示软中断安全的锁的数量为 0。
softirq-unsafe locks: 873:
表示软中断不安全的锁的数量为 873。
irq-safe locks: 28:
表示中断安全的锁的数量为 28。
irq-unsafe locks: 952:
表示中断不安全的锁的数量为 952。
hardirq-read-safe locks: 1:
表示硬中断读取安全的锁的数量为 1。
hardirq-read-unsafe locks: 97:
表示硬中断读取不安全的锁的数量为 97。
softirq-read-safe locks: 0:
表示软中断读取安全的锁的数量为 0。
softirq-read-unsafe locks: 93:
表示软中断读取不安全的锁的数量为 93。
irq-read-safe locks: 1:
表示中断读取安全的锁的数量为 1。
irq-read-unsafe locks: 97:
表示中断读取不安全的锁的数量为 97。
uncategorized locks: 421:
表示未分类的锁的数量为 421。
unused locks: 0:
表示未使用的锁的数量为 0。
max locking depth: 19:
表示最大的锁嵌套深度为 19。
max bfs queue depth: 581:
表示最大的广度优先搜索队列深度为 581。
chain lookup misses: 18695:
表示链查找未命中的次数为 18695。
chain lookup hits: 13102469:
表示链查找命中的次数为 13102469。
cyclic checks: 17833:
表示循环检查的次数为 17833。
redundant checks: 0:
表示冗余检查的次数为 0。
redundant links: 0:
表示冗余链接的数量为 0。
find-mask forwards checks: 1962:
表示前向查找掩码检查的次数为 1962。
find-mask backwards checks: 2025:
表示后向查找掩码检查的次数为 2025。
hardirq on events: 9076440:
表示在硬中断上开启锁的事件数为 9076440。
hardirq off events: 9076432:
表示在硬中断上关闭锁的事件数为 9076432。
redundant hardirq ons: 346:
表示硬中断上冗余的开启锁的次数为 346。
redundant hardirq offs: 196734:
表示硬中断上冗余的关闭锁的次数为 196734。
softirq on events: 97064:
表示在软中断上开启锁的事件数为 97064。
softirq off events: 97064:
表示在软中断上关闭锁的事件数为 97064。
redundant softirq ons: 0:
表示软中断上冗余的开启锁的次数为 0。
redundant softirq offs: 0:
表示软中断上冗余的关闭锁的次数为 0。
debug_locks: 0:
表示 debug_locks 配置选项的状态。
0
表示未启用 debug_locks。
zapped classes: 5:
表示已删除的锁类别数为 5。zapped classes 是指被删除的锁类别。
zapped lock chains: 5:
表示已删除的锁依赖关系链数为 5。zapped lock chains 是指被删除的锁依赖关系链。
large chain blocks: 1:
表示大链块的数量为 1。large chain blocks 是指由于空间不足而被压缩的锁依赖关系链。
lockdep_chains
功能:此文件用于查看内核中已识别的锁依赖关系链。
使用方法:同样,可以通过 cat 命令或其他文件查看工具来读取该文件的内容。
输出内容:该文件的输出包含多行,每一行描述一个锁依赖关系链,其中包含锁的名称和依赖关系信息。
cat /proc/lockdep_chains
.........................................................................
irq_context: 0
[000000001d1d1fd5] &ynr->mlock
[000000007d93a9dc] batched_entropy_u64.lock.lock.wait_lock
[000000000075849f] &dl_b->dl_runtime_lock
[00000000d1277727] rcu_tasks.cbs_wq.lock.lock.wait_lock
.........................................................................
irq_context: 0:
这是关系链的上下文描述,表示此锁依赖关系链未在中断上下文中。
[000000001d1d1fd5] &ynr->mlock:
[000000001d1d1fd5]
是锁的标识符,通常是锁的地址,用于唯一标识这个锁。&ynr->mlock
是锁的名称,表示锁是ynr
结构体中的mlock
成员。
[000000007d93a9dc] batched_entropy_u64.lock.lock.wait_lock:
[000000007d93a9dc]
是另一个锁的标识符,通常是锁的地址,用于唯一标识这个锁。batched_entropy_u64.lock.lock.wait_lock
是锁的名称,表示这是batched_entropy_u64.lock
锁的等待锁。
[000000000075849f] &dl_b->dl_runtime_lock:
[000000000075849f]
是另一个锁的标识符,通常是锁的地址,用于唯一标识这个锁。&dl_b->dl_runtime_lock
是锁的名称,表示锁是dl_b
结构体中的dl_runtime_lock
成员。
[00000000d1277727] rcu_tasks.cbs_wq.lock.lock.wait_lock:
[00000000d1277727]
是另一个锁的标识符,通常是锁的地址,用于唯一标识这个锁。rcu_tasks.cbs_wq.lock.lock.wait_lock
是锁的名称,表示这是rcu_tasks.cbs_wq.lock
锁的等待锁。
这个输出表示一个锁依赖关系链,锁之间通过依赖关系相互连接。例如,ynr->mlock
锁依赖于 batched_entropy_u64.lock.lock.wait_lock
锁,batched_entropy_u64.lock.lock.wait_lock
锁又依赖于 dl_b->dl_runtime_lock
锁,而 dl_b->dl_runtime_lock
锁又依赖于 rcu_tasks.cbs_wq.lock.lock.wait_lock
锁。这样的依赖关系链是 lockdep 检测到的,它有助于开发者了解内核中锁之间的相互依赖关系,以便调试和优化锁机制,确保系统的稳定性和性能。
参考资料:
魅族团队《Linux 死锁检测模块 Lockdep 简介》;