Fullmoon System

Linuxカーネルの構造:スケジューラー・メモリー・VFS・起動と障害診断

EdwardMoon

Linuxカーネルは、アプリケーションがCPU、メモリー、ディスク、ネットワークを安全に共有するためのOSの中核です。プロセスはカーネル関数を直接呼ばず、システムコールABIからサービスを要求します。カーネルは権限とリソースの状態を確認してハードウェア操作を行います。

この記事ではモノリシックという分類だけでなく、実サーバーで観測できるコマンドを使い、スケジューリング、仮想メモリー、VFS、起動、モジュール、パニックのつながりを確認します。根拠のないsysctl推奨値を適用しない診断原則も説明します。

Linuxカーネルの構造:ユーザー空間、システムコール、カーネルサブシステム、ハードウェア
ユーザー空間からシステムコール、カーネルサブシステム、ハードウェアへ続く実行境界

構造の全体像

Linuxは、性能が重要なスケジューラー、メモリー管理、VFS、ネットワークスタック、多くのドライバーをカーネルアドレス空間で実行するモノリシックカーネルです。一方、実行時に機能を追加・削除できるロード可能モジュールにも対応します。ユーザー空間とカーネル空間は、CPUの権限レベルとページテーブルの保護で分けられます。

主な構成障害の現れ方
ユーザー空間シェル、Webサーバー、DB、libcプロセス終了、遅延、エラーコード
システムコール境界openat、read、write、mmap、cloneEACCES、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_FIFOSCHED_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用のモジュールとツールを準備し、実ルートへ切り替えます。

  1. ファームウェアが起動項目を選び、ブートローダーかEFI stubを実行する。
  2. カーネルがCPU、メモリー、割り込み、初期ドライバーを設定する。
  3. initramfsの初期ユーザー空間が実ルートデバイスを準備する。
  4. 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 --systemsysctl -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つずつロールバック計画とともに検証してください。