kernel-internals について
kernel-internalsは、Linuxカーネルの調査を行うエージェント向けのスキルです。スケジューリング、メモリ管理、VFS、ページキャッシュ、OOMの解説に診断コマンドと一般的な調査手順を組み合わせています。
主な機能
- 01CFSとEEVDFのスケジューリング原理
- 02バディアロケーターとSLUBの分析
- 03kmallocとvmallocの使い分け
- 04VFSとページキャッシュの仕組み
- 05/proc/meminfoとOOMの診断
活用シーン
- 01スケジューリング遅延やCPU配分の偏りの調査
- 02カーネルメモリ割り当て失敗の分析
- 03ページキャッシュと先読み動作の確認
- 04メモリ圧迫とOOM対象選択の診断
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mohitmishra786/ low-level-dev-skills --skill kernel-internalsインストール後、Claude Code で/kernel-internalsを入力して読み込まれたか確認します。
詳細
カーネル内部
目的
エージェントがLinuxカーネル内部を理解するためのガイドです。CFSおよびEEVDFスケジューラー、ランキューとvruntime、バディアロケーターとSLUB、vmallocとkmallocの違い、VFSのdentry/inode/fileオブジェクト、ページキャッシュと先読み、メモリーゾーン、OOMキラーのヒューリスティクス、/proc/meminfoの解釈について説明します。
使用する場面
- スケジューリング遅延やCPU割り当ての不公平を診断する場合
- 大きなカーネル割り当てにおけるkmallocの失敗とvmallocの使い分けを理解する場合
- ページキャッシュの動作や先読みの効果を分析する場合
- メモリーが逼迫しているときに
/proc/meminfoを解釈する場合 - OOMキラーによる犠牲プロセスの選択をデバッグする場合
kernel/sched/、mm/、fs/のカーネルソースを読む場合
ワークフロー
1. スケジューラー — CFSとEEVDF
Linuxでは、CFSクラスのスケジューリングにEEVDF(Earliest Eligible Virtual Deadline First)を使用します。EEVDFは6.6(2023年)でオプションとしてマージされ、CFSからEEVDFへの段階的な移行は6.12(2024年11月)で完了しました。古い6.6~6.11カーネルでは、どちらのスケジューラーが有効か確認してください。ランキューやvruntime/ラグなどの基本概念は引き続き共通です。
Per-CPU runqueue (struct rq)
├── cfs_rq — fair-class tasks sorted by vruntime/deadline
├── rt_rq — real-time tasks (FIFO/RR)
└── dl_rq — SCHED_DEADLINE tasks
主な指標:
# Task scheduling info
chrt -p <pid>
cat /proc/<pid>/sched
# Runqueue latency (scheduler debugging)
cat /sys/kernel/debug/sched/debug # requires debugfs
# Trace scheduler events
perf sched record -a -- sleep 5
perf sched latency
vruntime — 消費したCPU時間を追跡する仮想実行時間です。vruntimeが小さいほど、CPUを割り当てられやすくなります。
# CFS tunables
sysctl kernel.sched_latency_ns
sysctl kernel.sched_min_granularity_ns
sysctl kernel.sched_wakeup_granularity_ns
2. EEVDFの詳細
EEVDFは、実行可能なタスクのうち仮想デッドラインが最も早いタスクを選択し、短いタイムスライスのタスクに対するレイテンシの公平性を高めます。ラグが正のタスクは実行可能であり、スケジューラーは実行可能なタスクの中から仮想デッドラインが最も早いものを選択します。
# Check kernel version (EEVDF transition complete in 6.12+)
uname -r
# Scheduler documentation
# docs.kernel.org/scheduler/sched-eevdf.html
3. メモリーサブシステム — バディアロケーター
物理ページは2のべき乗単位で割り当てられます(order 0 = 4KB、order 1 = 8KB、…)。
ZONE_DMA / ZONE_DMA32 / ZONE_NORMAL / ZONE_MOVABLE
└── free_area[MAX_ORDER] — buddy lists per order
# Buddy allocator stats
cat /proc/buddyinfo
# Per-zone page counts
cat /proc/zoneinfo | head -80
4. SLUBアロケーター
kmallocのデフォルトバックエンドです。一般的なサイズ向けのCPUごとのキャッシュ(スラブ)を使用します。
# SLUB debug (requires CONFIG_SLUB_DEBUG)
cat /sys/kernel/slab/*/objects 2>/dev/null | head
# kmalloc size classes visible in /proc/slabinfo
cat /proc/slabinfo | head -20
| API | 使用する場面 |
|---|---|
kmalloc(size, GFP_KERNEL) | 約128KB以下(アーキテクチャに依存)、物理的に連続 |
kzalloc(size, flags) | ゼロ初期化されたkmalloc |
vmalloc(size) | 大きなサイズ、仮想的に連続(物理メモリーは断片化している場合があります) |
get_free_pages() | ページを直接割り当てる |
// Kernel module allocation example
void *buf = kmalloc(4096, GFP_KERNEL);
if (!buf)
return -ENOMEM;
kfree(buf);
5. Highmem
32ビット環境または特定の構成では、ZONE_HIGHMEMに、カーネルの仮想アドレス空間へ恒久的にマッピングされていないページが格納されます。64ビットのx86/arm64では、ほぼすべてのRAMがZONE_NORMALにあります。
grep -i highmem /proc/zoneinfo
6. VFSレイヤー
Path lookup: /home/user/file.txt
├── dentry cache (dcache) — directory entry tree
├── inode — metadata (permissions, size, ops)
└── file — per-open-file state (offset, flags)
# Mounted filesystems
cat /proc/mounts
# Inode/dentry cache pressure
sysctl vm.vfs_cache_pressure # higher = reclaim caches sooner
# File descriptor usage
ls /proc/<pid>/fd | wc -l
7. ページキャッシュと先読み
# Drop caches (testing only — destructive to perf)
sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
# Readahead tuning
blockdev --getra /dev/sda
blockdev --setra 4096 /dev/sda
# Per-file cache status
cat /proc/<pid>/smaps_rollup
ページキャッシュのページは、meminfoではCachedとして表示されます。ダーティーページは書き戻しを待機しています。
8. /proc/meminfoの解釈
cat /proc/meminfo
| フィールド | 意味 |
|---|---|
MemTotal | 使用可能なRAMの合計 |
MemFree | 完全に未使用のページ |
MemAvailable | 割り当て可能なメモリーの推定値(回収可能なキャッシュを含む) |
Cached | ページキャッシュ+tmpfs |
Buffers | ブロックデバイスのメタデータキャッシュ |
SwapTotal / SwapFree | スワップ領域 |
Dirty | 書き戻し待ちのページ |
AnonPages | 匿名ページ(ヒープ/スタック) |
Slab | カーネルオブジェクトキャッシュ |
SReclaimable | 回収可能なスラブ |
SUnreclaim | カーネル構造体(簡単には回収できません) |
Memory pressure diagnosis
├── MemAvailable low + Cached high → page cache reclaim candidate
├── AnonPages high + SwapFree low → OOM risk
├── Slab huge → kernel object leak; check /proc/slabinfo
└── Dirty high → slow writeback; check I/O scheduler
9. OOMキラー
# OOM score per process (higher = more likely victim)
cat /proc/<pid>/oom_score
cat /proc/<pid>/oom_score_adj # -1000 to 1000, admin adjustment
# OOM events in kernel log
dmesg | grep -i "out of memory"
journalctl -k | grep -i oom
OOMキラーは、メモリー使用量、子プロセス、oom_score_adjを考慮したoom_scoreに基づいてプロセスを選択します。重要なデーモンを保護するには、次のようにします。
# Protect process from OOM (requires root)
echo -1000 | sudo tee /proc/<pid>/oom_score_adj
よくある問題
| 症状 | 原因 | 対処法 |
|---|---|---|
kmalloc: allocation failed | 断片化、またはサイズが大きすぎる | vmallocを使用する。メモリー圧迫を軽減する。必要な場合に限りGFP_ATOMICを使用する |
| iowaitが高く、MemAvailableが少ない | ページキャッシュのスラッシング | RAMを増設する。vfs_cache_pressureを調整する |
| OOMによって誤ったプロセスが強制終了される | メモリー使用量の多いプロセスのadj値が低い | oom_score_adjを設定する。cgroupsのmemory.maxを使用する |
| スケジューリングが不公平 | RTタスクがCFSを飢餓状態にする | chrtを確認する。isolcpusでCPUを分離する |
| SLUBの破損 | モジュール内のuse-after-free | KASANを有効にする。slub_debugを使って監査する |
| ファイルの読み取りが遅い | 先読みが小さすぎる | 先読みを増やす。バックエンドデバイスを確認する |
関連スキル
skills/kernel/device-drivers— これらのサブシステムを使用する char/platform ドライバーskills/kernel/kernel-debugging— 内部調査用の ftrace、kgdbskills/low-level-programming/linux-kernel-modules— LKM 開発の基礎skills/kernel/kernel-testing— サブシステムの単体テスト用 KUnitskills/profilers/linux-perf— perf sched とメモリのプロファイリングskills/observability/ebpf— ユーザー空間からスケジューラーとメモリのイベントをトレース