カーネルデッドロックのデバッグ方法〜

デッドロックが発生した場合、関連する問題を見つけて解決するためにどのような方法を使用できますか。

lockdepデッドロック検出モジュール

LinuxカーネルはデッドロックデバッグモジュールLockdepを提供します。これは、各ロックの状態と各ロック間の依存関係を追跡し、一連の検証ルールを実行して、ロック間の依存関係が正しいことを確認します。カーネルは2006年に導入されました(https://lwn.net/Articles/185666/)。

Lockdepを有効にする

Lockdepによって検出されるロックには、スピンロック、rwlock、mutex、rwsemデッドロック、ロックの誤った解放、およびアトミック操作でのスリープエラーが含まれます。

以下は、lockcepカーネルオプションとその説明です。

CONFIG_DEBUG_RT_MUTEXES = y
は、rt mutexのデッドロックを検出し、デッドロックサイト情報を自動的に報告します。

CONFIG_DEBUG_SPINLOCK = y
は、スピンロックの初期化されていない使用などの問題を検出します。NMIウォッチドッグとともに使用すると、スピンロックデッドロックを見つけることができます。

CONFIG_DEBUG_MUTEXES = y
は、ミューテックスエラーを検出して報告します

CONFIG_DEBUG_WW_MUTEX_SLOWPATH = y
は、待機/巻線タイプのミューテックスのスローパステストを検出します。

CONFIG_DEBUG_LOCK_ALLOC = y
は、使用中のロック(spinlock / rwlock / mutex / rwsem)が解放されるか、使用中のロックが再初期化されるか、プロセスの終了時にロックが保持されることを検出します。

CONFIG_PROVE_LOCKING = yを
使用すると、カーネルはデッドロックが発生する前にデッドロックの詳細を報告できます。/ proc / lockdep_chainsを参照してください。

CONFIG_LOCKDEP =
yLockdep全体のマスタースイッチ。/ proc / lockdep、/ proc / lockdep_statsを参照してください。

CONFIG_LOCK_STAT = y
は、待機時間、保持時間など、ロック保持競技エリアの情報を記憶します。/ proc / lock_statを参照してください。

CONFIG_DEBUG_LOCKDEP = y
は、Lockdepの使用中にさらに多くのセルフチェックを実行します。これにより、多くの余分なオーバーヘッドが増加します。

CONFIG_DEBUG_ATOMIC_SLEEP = y
アトミックpでスリープすると、多くの予測できない問題が発生する可能性があります。これらのアトミックpには、スピンロックロック、rcu読み取り操作、カーネルプリエンプションの禁止、割り込み処理などが含まれます。

関連するカーネルノードをロックする

/ proc / sys / kernel / lock_statが
設定されている場合、/ proc / lock_statの統計を表示し、クリアされている場合はlockdepの統計をオフにすることができます。

/ proc / sys / kernel / max_lock_depth

/ proc / sys / kernel / promise_locking

/ proc / locks


ロック使用統計に関する/ proc / lock_stat

/ proc / lockdep
には依存ロックがあります

/ proc / lockdep_statsに
は依存関係ロック統計があります

/ proc / lockdep_chains
依存関係ロックリンクリスト

カーネルは、ロック使用の問題の発見を支援するトレースポイントも提供します:/ sys / kernel / debug / traceing / events / lock。

Lockdepテスト

spin_lockデッドロックをテストする

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("al: lockdep error test init\n");
  hack_spinAB();
  hack_spinBA();
  return 0;
}

実行後、デッドロックの説明からデッドロックタイプを知ることができます次に、デッドロックポイントを詳細に紹介ます。この時点で、どのロックがどのロックでデッドロックが発生したかを大まかに知ることができます。次は、デッドロックの詳細なバックトレースです。これは、デッドロックが発生したときのスタックバックトレースの分析に役立ちます。

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锁

but task is already holding lock:
(hack_spinB){+.+...}, at: [<bf000038>] hack_spinAB+0x38/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_spinAB+0x30/0x3c [lock]
#1: (hack_spinB){+.+...}, at: [<bf000038>] hack_spinAB+0x38/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_stack+0x20/0x24)
[<c0012e7c>] (show_stack) from [<c05ade10>] (dump_stack+0x8c/0xb4)
[<c05ade10>] (dump_stack) from [<c006b988>] (__lock_acquire+0x1aa4/0x1f64)
[<c006b988>] (__lock_acquire) from [<c006c55c>] (lock_acquire+0xf4/0x190)
[<c006c55c>] (lock_acquire) from [<c05b4ec8>] (_raw_spin_lock+0x60/0x98)
[<c05b4ec8>] (_raw_spin_lock) from [<bf002030>] (lockdep_test_init+0x30/0x3c [lock])
......
[<c00a4ddc>] (load_module) from [<c00a55fc>] (SyS_init_module+0x140/0x150)
[<c00a55fc>] (SyS_init_module) from [<c000ec80>] (ret_fast_syscall+0x0/0x4c)
INFO: rcu_sched self-detected stall on CPU
0: (2099 ticks this GP) idle=5ed/140000000000001/0 softirq=13024/13024 fqs=1783 
(t=2100 jiffies g=-51 c=-52 q=22)
Task dump for CPU 0:
insmod R running 0 658 657 0x00000002
[<c00171b4>] (unwind_backtrace) from [<c0012e7c>] (show_stack+0x20/0x24)
[<c0012e7c>] (show_stack) from [<c0052874>] (sched_show_task+0x128/0x184)
......
[<c0008740>] (gic_handle_irq) from [<c0013a44>] (__irq_svc+0x44/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_lock+0xf0/0x1e0)
[<c0070cb4>] (do_raw_spin_lock) from [<c05b4eec>] (_raw_spin_lock+0x84/0x98)
[<c05b4eec>] (_raw_spin_lock) from [<bf002030>] (lockdep_test_init+0x30/0x3c [lock])
......
BUG: spinlock lockup suspected on CPU#0, insmod/658--------错误类型是spinlock,下面的backtrace和上面基本一致。
lock: hack_spinB+0x0/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_stack+0x20/0x24)
[<c0012e7c>] (show_stack) from [<c05ade10>] (dump_stack+0x8c/0xb4)
[<c05ade10>] (dump_stack) from [<c0070b2c>] (spin_dump+0x8c/0xd0)
......

ミューテックスデッドロックをテストする

======================================================
[ INFO: possible circular locking dependency detected ]
4.0.0+ #92 Tainted: G           O   
-------------------------------------------------------
kworker/1:1/343 is trying to acquire lock:
 (mutex_a){+.+...}, at: [<bf000080>] lockdep_test_worker+0x24/0x58 [mutexlock]

but task is already holding lock:
 ((&(&delay_task)->work)){+.+...}, at: [<c0041078>] process_one_work+0x130/0x60c

which lock already depends on the new lock.

the existing dependency chain (in reverse order) is:

-> #1 ((&(&delay_task)->work)){+.+...}:
       [<c00406f4>] flush_work+0x4c/0x2bc
       [<c0041cc4>] __cancel_work_timer+0xa8/0x1d0
       [<c0041e28>] cancel_delayed_work_sync+0x1c/0x20
       [<bf000138>] lockdep_thread+0x84/0xa4 [mutexlock]
       [<c0046ee0>] kthread+0x100/0x118
       [<c000ed50>] ret_from_fork+0x14/0x24

-> #0 (mutex_a){+.+...}:
       [<c006c55c>] lock_acquire+0xf4/0x190
       [<c05b09e4>] mutex_lock_nested+0x90/0x480
       [<bf000080>] lockdep_test_worker+0x24/0x58 [mutexlock]
       [<c0041138>] process_one_work+0x1f0/0x60c
       [<c0041fd0>] worker_thread+0x54/0x530
       [<c0046ee0>] kthread+0x100/0x118
       [<c000ed50>] ret_from_fork+0x14/0x24

other info that might help us debug this:

 Possible unsafe locking scenario:

       CPU0                    CPU1
       ----                    ----
  lock((&(&delay_task)->work));
                               lock(mutex_a);
                               lock((&(&delay_task)->work));
  lock(mutex_a);

 *** DEADLOCK ***

2 locks held by kworker/1:1/343:
 #0:  ("events"){.+.+.+}, at: [<c0041078>] process_one_work+0x130/0x60c
 #1:  ((&(&delay_task)->work)){+.+...}, at: [<c0041078>] process_one_work+0x130/0x60c
stack backtrace:
CPU: 1 PID: 343 Comm: kworker/1:1 Tainted: G           O    4.0.0+ #92
Hardware name: ARM-Versatile Express
Workqueue: events lockdep_test_worker [mutexlock]
<c00171b4>] (unwind_backtrace) from [<c0012e7c>] (show_stack+0x20/0x24)
[<c0012e7c>] (show_stack) from [<c05ade10>] (dump_stack+0x8c/0xb4)
[<c05ade10>] (dump_stack) from [<c0065e80>] (print_circular_bug+0x21c/0x344)
[<c0065e80>] (print_circular_bug) from [<c006be44>] (__lock_acquire+0x1f60/0x1f64)
[<c006be44>] (__lock_acquire) from [<c006c55c>] (lock_acquire+0xf4/0x190)
[<c006c55c>] (lock_acquire) from [<c05b09e4>] (mutex_lock_nested+0x90/0x480)
[<c05b09e4>] (mutex_lock_nested) from [<bf000080>] (lockdep_test_worker+0x24/0x58 [mutexlock])
[<bf000080>] (lockdep_test_worker [mutexlock]) from [<c0041138>] (process_one_work+0x1f0/0x60c)
[<c0041138>] (process_one_work) from [<c0041fd0>] (worker_thread+0x54/0x530)
[<c0041fd0>] (worker_thread) from [<c0046ee0>] (kthread+0x100/0x118)
[<c0046ee0>] (kthread) from [<c000ed50>] (ret_from_fork+0x14/0x24)

CONFIG_PROVE_LOCKINGをオンにすると、関連するトレースが出力されます。

lockdep_test_worker
  ->mutex_lock(&mutex_a)
    ->mutex_lock_nested
      ->__mutex_lock_common
        ->mutex_acquire_nest
          ->lock_acquire_exclusive
            ->lock_acquire
              ->__lock_acquire---------下面的validate_chain在打开CONFIG_PROVE_LOCKING才会进行检查。
                ->validate_chain->...->print_circular_bug

1.国内のRISC-VコアMCUメーカーの在庫!

2.組み込み産業の経済発展とEUの産業発展のバロメーターに注目しましたか?

3.技術系従業員の離職費用はどのくらいですか?

4.新しい世界、新しい方法:2021年の国際組み込み展示会と会議がデジタル化

5.国内のLinuxオペレーティングシステムのアーキテクチャはどのように設計されていますか?

6.人工知能の紹介:LinuxとPythonに基づくニューラルネットワーク

免責事項:この記事はオンラインで複製されており、著作権は原作者に帰属します。作品の著作権にかかわる場合は、お問い合わせください。ご提供いただいた著作権認定資料に基づいて著作権を確認し、作者の報酬を支払うか、コンテンツを削除します。

おすすめ

転載: blog.csdn.net/DP29syM41zyGndVF/article/details/114324390