Linuxカーネルの構造:スケジューラー・メモリー・VFS・起動と障害診断
EdwardMoon
Linuxカーネルは、アプリケーションがCPU、メモリー、ディスク、ネットワークを安全に共有するためのOSの中核です。プロセスはカーネル関数を直接呼ばず、システムコールABIからサービスを要求します。カーネルは権限とリソースの状態を確認してハードウェア操作を行います。
この記事ではモノリシックという分類だけでなく、実サーバーで観測できるコマンドを使い、スケジューリング、仮想メモリー、VFS、起動、モジュール、パニックのつながりを確認します。根拠のないsysctl推奨値を適用しない診断原則も説明します。

構造の全体像
Linuxは、性能が重要なスケジューラー、メモリー管理、VFS、ネットワークスタック、多くのドライバーをカーネルアドレス空間で実行するモノリシックカーネルです。一方、実行時に機能を追加・削除できるロード可能モジュールにも対応します。ユーザー空間とカーネル空間は、CPUの権限レベルとページテーブルの保護で分けられます。
| 層 | 主な構成 | 障害の現れ方 |
|---|---|---|
| ユーザー空間 | シェル、Webサーバー、DB、libc | プロセス終了、遅延、エラーコード |
| システムコール境界 | openat、read、write、mmap、clone | EACCES、ENOMEM、EIOなどのerrno |
| カーネル空間 | スケジューラー、MM、VFS、ネットワーク、LSM、ドライバー | 警告、Oops、パニック、リソース圧力 |
| ハードウェア | CPU、RAM、ブロックデバイス、NIC | マシンチェック、I/Oエラー、割り込み異常 |
現在のカーネルと実行環境を確認する
uname -a
cat /etc/os-release
cat /proc/cmdline
systemd-detect-virt
cat /proc/sys/kernel/tainted
最後の値が0以外なら、独自ライセンスのモジュール、強制的なモジュール削除、ハードウェアエラーなどによってtaintedになっている場合があります。数値だけで結論を出さず、公式のtaintビットの説明とカーネルログを併せて確認します。
主要サブシステム
| サブシステム | 役割 | 主な観測手段 |
|---|---|---|
| スケジューラー | 実行可能タスクを、いつ、どのCPUで動かすか決定 | ps、schedstat、perf sched |
| メモリー管理 | 仮想アドレス、ページフォルト、ページキャッシュ、reclaim、NUMA方針を管理 | /proc/meminfo、vmstat |
| VFS | 異なるFSに共通のAPIとオブジェクトモデルを提供 | findmnt、stat、/proc/filesystems |
| ネットワーク | ソケット、TCP/IP、ルーティング、Netfilter、デバイスキューを処理 | ss、ip、nstat |
| セキュリティ | DAC、capabilities、LSM、seccompなどでアクセス制御 | id、getcap、ausearch |
| ドライバー | バスと機器を検出し、共通カーネルインターフェースへ接続 | lspci -k、lsmod、modinfo |
システムコールの境界
アプリケーションは通常libcのラッパーを使いますが、libcが必須経路というわけではありません。アーキテクチャ固有のシステムコール命令と呼出規約を直接使うこともできます。カーネルが番号、引数、権限を確認して内部実装へ渡します。「glibcがシステムコールを処理する」より、「glibcがよく使われる便利なラッパーを提供する」が正確です。
straceでファイルを開く経路を見る
strace -f -e trace=openat,read,write,close cat /etc/hostname
# 要約統計だけを確認
strace -c cat /etc/hostname
新しいglibc環境では、ファイルを開く処理がopen()ではなくopenat()系として表示される場合があります。ユーザー関数と実システムコールの名前が常に同じとは考えないでください。
CFSとEEVDFスケジューラー
Linuxの通常タスクのスケジューリングはプリエンプティブです。CFSを非プリエンプティブと説明するのは誤りです。また6.6からは、通常のスケジューリングがCFSの仮想実行時間モデルからEEVDFへ移行し始めました。配布元によるバックポートもあるため、名前だけで断定せず、実カーネルと提供元の資料を確認します。
uname -r
ps -eo pid,tid,psr,cls,pri,ni,stat,comm --sort=-pri | head -n 20
chrt -p $$
cat /proc/$$/sched | head -n 30
注意:通常タスクのCFS・EEVDFと、リアルタイム方針のSCHED_FIFO、SCHED_RR、デッドライン方針を混同しないでください。リアルタイム優先度を誤ると管理シェルや重要デーモンが実行時間を得られなくなるため、本番で任意に変更しないでください。
仮想メモリーとページキャッシュ
プロセスの仮想アドレスは、MMUとページテーブルで物理メモリーやファイルへ対応付けられます。匿名メモリー、ファイルマッピング、ページキャッシュ、slab、reclaim、swapは相互に影響します。freeのfree列だけで不足と判断せず、available、swap、page fault、reclaim、PSIを併せて見ます。
free -h
grep -E 'MemAvailable|Cached|Swap|Slab|SReclaimable' /proc/meminfo
vmstat 1 10
cat /proc/pressure/memory
ps -eo pid,comm,rss,vsz,%mem --sort=-rss | head -n 20
プロセスのアドレス空間を確認する
PID=1234
pmap -x "$PID" | tail -n 20
cat "/proc/$PID/status" | grep -E 'VmRSS|VmSwap|Threads'
cat "/proc/$PID/smaps_rollup"
VmRSSは共有ページを含むため、単純合計すると実物理メモリーを超える場合があります。共有部分を按分するPSSが必要ならsmaps_rollupを使います。
VFSとファイルI/O
VFSはext4、XFS、Btrfs、NFSなどに共通インターフェースを提供します。pathnameはdentry cacheを経てinodeへ解決され、開かれたファイルはプロセスのFDテーブルからカーネルのfileオブジェクトを参照します。削除後も開いたままなら、パスが消えてもブロックが解放されないのは、この参照関係のためです。
cat /proc/filesystems
findmnt -o TARGET,SOURCE,FSTYPE,OPTIONS
stat /var/log/messages
sudo lsof +L1
cat /proc/sys/fs/file-nr
容量エラーでは、ブロック、inode、開いたままの削除済みファイルを分けて調べます。詳しくはNo space left on device診断ガイドを参照してください。
起動とinitramfs
一般的なUEFIシステムは、ファームウェア、ブートローダー、カーネルとinitramfs、実ルートFS、PID 1の順に起動します。initramfsは通常圧縮cpioアーカイブとして渡され、初期ユーザー空間を提供します。ストレージ、暗号化、LVM、RAID用のモジュールとツールを準備し、実ルートへ切り替えます。
- ファームウェアが起動項目を選び、ブートローダーかEFI stubを実行する。
- カーネルがCPU、メモリー、割り込み、初期ドライバーを設定する。
- initramfsの初期ユーザー空間が実ルートデバイスを準備する。
- switch_root後、実ルートのPID 1がサービスとログイン環境を起動する。
cat /proc/cmdline
systemd-analyze time
systemd-analyze critical-chain
journalctl -b -k -p warning
# RHEL/Rocky系で現在のinitramfsの内容を確認
lsinitrd "/boot/initramfs-$(uname -r).img" | less
initramfsの再生成やGRUB変更は起動不能につながる場合があります。遠隔サーバーではコンソール、以前のカーネル、起動可能なバックアップ、復旧手順を確保してから、配布元の資料に従って作業します。
モジュールとドライバーの診断
モジュールはカーネル内で高権限で動くため、ユーザープログラムとは失敗時の影響が異なります。機器が見えない場合は、無闇にモジュールを抜き差しせず、デバイス、結び付いたドライバー、署名、カーネルログの順に確認します。
lspci -nnk
lsmod | head
modinfo <module_name>
journalctl -k -b | grep -Ei 'firmware|module|driver|taint|error'
cat /proc/sys/kernel/tainted
modprobe -rは使用中のストレージ・ネットワークドライバーを切り離す場合があります。本番では依存関係と影響範囲を確認し、保守時間とコンソールを確保するまで実行しないでください。
カーネルパニックの診断
Kernel Oopsはエラー記録後も実行を続ける場合がありますが、信頼性はすでに損なわれている可能性があります。Kernel Panicは正常実行を継続できないと判断した状態で、設定によって停止、一定時間後の再起動、kdumpのキャプチャ用カーネルへの移行が起こります。常に「保護のためのシャットダウン」とは限りません。
journalctl -k -b -1 -p warning..alert
last -x | head -n 20
sudo kdumpctl status
sysctl kernel.panic kernel.panic_on_oops
ls -lh /var/crash
調査の順序
- 直近のカーネル、ドライバー、ファームウェア、ハードウェア変更時点を確認する。
- コンソールまたは遠隔管理装置のパニック画面全体と最初のエラーを保存する。
- kdumpが準備済みなら、vmcoreと同一ビルドのデバッグシンボルを確保する。
- 以前のカーネルでの再現可否から、回帰とハードウェア問題を切り分ける。
- 本番サーバーで意図的なパニックを発生させない。
sysctlは測定、仮説、ロールバックの順で扱う
sysctl --systemとsysctl -pは実際のカーネルへ設定を適用します。構文検査や読み取り専用の診断として実行しないでください。次のパスは実在するローカル設定へ置き換えます。適用が必要な場合に限り、変更前の値と復帰コマンドを準備し、変更時間帯に別途実施します。
すべてのWebサーバーに通用する万能な値はありません。カーネル、メモリー、接続パターン、アプリケーションキュー、コンテナ制限でボトルネックは変わります。特にtcp_tw_reuse、ポート範囲、backlog、swappinessを根拠なく一括変更すると、原因が見えにくくなります。
# 1. 現在の値と関連指標を読み取ります。
sysctl vm.swappiness net.core.somaxconn net.ipv4.ip_local_port_range
ss -s
vmstat 1 10
# 2. 設定ファイルを読み取り専用で確認します。値は適用しません。
sudo find /etc/sysctl.d /run/sysctl.d /usr/local/lib/sysctl.d /usr/lib/sysctl.d \
-maxdepth 1 -type f -name '*.conf' -print 2>/dev/null
sudo cat /etc/sysctl.conf
# 3. 確認対象のファイルを指定し、内容と現在のカーネル値を照合します。
sudo cat /etc/sysctl.d/99-local.conf
sysctl vm.swappiness net.core.somaxconn net.ipv4.ip_local_port_range
これは値の推奨ではなく、変更前後を観測する枠組みです。変更は1つずつ行い、p95・p99遅延、エラー率、再送、メモリー圧力などの成功基準と、即座に戻せる値を記録します。
10分で行う診断の順序
# 1. バージョン、起動、taint
uname -r
uptime
cat /proc/sys/kernel/tainted
# 2. CPU、メモリー、I/Oの圧力
vmstat 1 10
cat /proc/pressure/{cpu,memory,io}
# 3. 最近のカーネル警告と失敗したunit
journalctl -k -b -p warning..alert
systemctl --failed
# 4. ファイルシステムと開いたままの削除済みファイル
df -hT
df -i
sudo lsof +L1
診断は、最初にチューニング値を変える作業ではありません。時間軸を合わせ、飽和したリソースと、カーネル警告・アプリケーションエラーのどちらが先かを確認してから、再現可能な仮説を立てます。
よくある誤解
| 誤りやすい説明 | 正確な説明 |
|---|---|
| CFSは非プリエンプティブ | 通常のLinuxスケジューリングはプリエンプティブで、6.6からEEVDFへの移行が進んだ。 |
| glibcがシステムコールを処理する | libcは一般にラッパーを提供し、権限切り替えと実処理はカーネルが行う。 |
| freeが少なければメモリー不足 | available、reclaim、swap、PSI、ワークロード指標を併せて見る。 |
| パニックは必ず即時終了 | timeoutとkdump設定により停止、再起動、ダンプ取得が異なる。 |
| sysctl推奨値は全サーバー共通 | カーネル、ハードウェア、通信に合わせて測定し、1つずつ検証する。 |
公式資料と次の学習
まとめ
カーネル構造の理解とは用語の暗記ではなく、ユーザー空間の症状をシステムコール、スケジューラー、メモリー、VFS、ドライバーへ結び付ける力です。現在のバージョンとログを保存し、観測値で問題の層を絞ってから、変更を1つずつロールバック計画とともに検証してください。