このページの目次

デバッグとテスト

カバー範囲: printk/dynamic debug → KGDB → KUnit → kselftest → LTP → syzkaller → fault injection → lockdep 統合 カーネルバージョン: 2.6 ~ 6.x

printk: カーネルログ

// kernel/printk/printk.c
printk(KERN_ERR "error: %d\n", err);

// ログレベルによるフィルタリング:
//   KERN_EMERG(0) KERN_ALERT(1) KERN_CRIT(2) KERN_ERR(3)
//   KERN_WARNING(4) KERN_NOTICE(5) KERN_INFO(6) KERN_DEBUG(7)

// コンソール出力のフィルタリング:
echo 4 > /proc/sys/kernel/printk  // ERROR 以上のメッセージのみをコンソールに出力

// 5.5 以降の構造化ログ: dev_printk, pr_fmt

Dynamic Debug

# モジュール/関数/ファイル/行番号ごとにデバッグログを有効化 (ランタイム、再コンパイル不要)
echo "module nfs +p" > /sys/kernel/debug/dynamic_debug/control
echo "func tcp_rcv_established +p" > dynamic_debug/control
echo "file fs/nfs/* +p" > dynamic_debug/control
# p=printk, f=関数名を含める, l=行番号を含める, t=スレッドIDを含める

# 有効化されたエントリを確認
cat /sys/kernel/debug/dynamic_debug/control | grep "=p"

KGDB: カーネルレベルの GDB

# シリアル経由でカーネルをリモートデバッグ (gdbserver に類似)
# ブート引数: kgdboc=ttyS0,115200 kgdbwait
# gdb vmlinux → target remote /dev/ttyS0 → ブレークポイント設定、ステップ実行
# SysRq-g で KGDB に進入

echo g > /proc/sysrq-trigger  # KGDB への進入をトリガー

KUnit: カーネルユニットテスト

// lib/kunit/
// ユーザーランドのユニットテストフレームワークに類似し、カーネル内で完全に実行される
#include <kunit/test.h>

static void my_test(struct kunit *test) {
    KUNIT_EXPECT_EQ(test, my_function(42), 84);
}

static struct kunit_case my_test_cases[] = {
    KUNIT_CASE(my_test),
    {},
};

// 実行方法: ビルド時に組み込み → 起動時に自動実行 → 結果は dmesg で確認

kselftest: カーネル自前テストスイート

# カーネルに内蔵されたテスト (tools/testing/selftests/)
make -C tools/testing/selftests TARGETS=net run_tests
make -C tools/testing/selftests TARGETS=bpf run_tests

# カバー範囲: システムコール、メモリ管理、ネットワーク、BPF、ファイルシステムなど

Syzkaller: ファズテスト

Syzkaller: カバレッジ誘導の自律型カーネルファザー ランダムな syscall シーケンスの生成 (カバレッジ誘導) QEMU VM 内で実行 クラッシュ/ハングを検出 再現 + 報告 (自動バイセクト) 5000 以上のカーネルバグを発見 —— カバレッジ誘導によるランダムな syscall シーケンスが QEMU 内で継続的にクラッシュ/ハングを掘り起こす デプロイ: github.com/google/syzkaller

LTP (Linux Test Project)

# 最大規模のカーネル/glibc 回帰テストスイート (github.com/linux-test-project/ltp)
./runltp -f syscalls       # システムコールテスト
./runltp -f mm             # メモリ管理
./runltp -f fs             # ファイルシステム

Fault Injection (障害注入)

# 障害注入フレームワーク: 各種ハードウェア/メモリ/IO の障害をシミュレート
# エラー処理パスが正しく動作するか確認

# メモリ割り当て失敗のシミュレーション:
echo 100 > /sys/kernel/debug/failslab/interval  # 100 回の slab alloc ごとに 1 回失敗

# IO エラーのシミュレーション:
echo 1 > /sys/kernel/debug/fail_make_request/times

参考

  • ソースコード⁠: kernel/printk/, kernel/debug/, lib/kunit/, tools/testing/selftests/
  • カーネルドキュメント⁠: Documentation/dev-tools/, Documentation/admin-guide/dynamic-debug-howto.rst
  • ツール⁠: syzkaller (github.com/google/syzkaller), LTP (github.com/linux-test-project/ltp)

キーワード: printk, dynamic debug, KGDB, KUnit, kselftest, syzkaller, LTP, fault injection