テックカリキュラム

Linuxカーネル・システムコール・性能解析

Linuxカーネル・システムコール・性能解析

インフラ応用編のChapter 1では、Linuxサーバ内部で実際に何が起きているのかを、 カーネル・システムコール・CPUスケジューリング・仮想メモリ・I/Oの観点から深く理解する。
単にLinuxコマンドを使える状態ではなく、CPU使用率の上昇、Load Averageの悪化、 メモリ不足、I/O Waitなどの現象について「なぜ発生しているのか」をOS内部の挙動から説明し、 ボトルネックを特定できるレベルを目指す。


1. User SpaceとKernel Space

Linuxでは、システム全体が大きく「User Space」と「Kernel Space」に分離されている。

■ User Space

一般的なアプリケーションが動作する領域である。

  • Webサーバ
  • データベース
  • Java / Pythonなどのアプリケーション
  • シェル

User Spaceのプログラムは、ハードウェアを自由に直接操作することはできない。

■ Kernel Space

OSの中核であるLinuxカーネルが動作する領域である。

  • CPU管理
  • メモリ管理
  • プロセス管理
  • ファイルシステム
  • ネットワーク
  • デバイス制御

アプリケーションがディスクやネットワークなどを利用するときは、 カーネルに処理を依頼する必要がある。


2. システムコールの内部構造

User SpaceのプログラムがKernel Spaceの機能を利用するためのインターフェースが System Call(システムコール)である。

代表的なシステムコールには以下がある。

  • read():データの読み込み
  • write():データの書き込み
  • open():ファイルを開く
  • close():ファイルを閉じる
  • fork():プロセス生成
  • execve():プログラム実行
  • mmap():メモリマッピング
  • socket():ソケット生成

例えばアプリケーションがファイルを読み込む場合、 概念的には以下のような処理が行われる。


Application
    ↓
read()
    ↓
System Call
    ↓
Linux Kernel
    ↓
File System
    ↓
Storage Device

つまり、アプリケーション性能を理解するためには、 アプリケーションコードだけではなくシステムコールまで追跡する必要がある。


3. CPUスケジューリング

実際のLinuxサーバでは、多数のプロセスやスレッドが同時に存在する。 しかし、CPUコアが一度に実行できる処理には限界がある。

そこでLinuxカーネルのSchedulerが、どのタスクにCPU時間を割り当てるかを管理する。

■ スケジューラが考慮する要素

  • 実行可能なタスク数
  • 優先度
  • CPU使用時間
  • CPUコアの負荷
  • タスクの性質

大量の実行可能タスクが存在すると、 CPUを取得できず待機するプロセスが増加する。

そのためCPU使用率だけを見るのではなく、 Run Queueなども確認する必要がある。


4. Load Averageを正しく理解する

Linux運用で頻繁に利用される指標の一つがLoad Averageである。


$ uptime

load average: 2.15, 1.87, 1.43

一般的に表示される3つの値は、 直近1分・5分・15分のシステム負荷を表している。

ただし、Load Averageを単純に「CPU使用率」と考えてはいけない。 Linuxでは、CPU実行待ちだけでなく特定の割り込み不能な待機状態もLoad Averageに影響する。

したがって、Load Averageが高い場合には、 CPUだけでなくI/Oなども含めて原因を調査する必要がある。

■ CPUコア数との関係

例えば4コアCPUでLoad Averageが4前後の場合と、 1コアCPUで4の場合では意味が大きく異なる。

Load Averageは、CPUコア数やタスク状態と組み合わせて評価することが重要である。


5. 仮想メモリの内部構造

Linuxでは、各プロセスが物理メモリを直接操作するのではなく、 Virtual Memory(仮想メモリ)を利用する。


Process
   ↓
Virtual Address
   ↓
Page Table
   ↓
Physical Address
   ↓
RAM

この仕組みにより、プロセスごとに独立したアドレス空間を提供できる。

■ Page

仮想メモリはPageと呼ばれる単位で管理される。

■ Page Table

仮想アドレスと物理アドレスの対応関係を管理する。

■ TLB(Translation Lookaside Buffer)

アドレス変換結果をキャッシュすることで、 Page Tableへのアクセスを高速化する。

大規模なデータ処理では、TLB MissやPage Faultなどが 性能に影響する場合がある。


6. Page FaultとSwap

プロセスがアクセスしようとしたページが期待した状態で物理メモリ上に存在しない場合、 Page Faultが発生する。

Page Faultには、比較的低コストで処理できるものと、 ストレージI/Oを伴う高コストなものが存在する。

■ Swap

メモリが不足すると、Linuxは一部のメモリ内容をSwap領域へ退避させる場合がある。


RAM
 ↓
Swap
 ↓
SSD / HDD

ストレージはRAMより大幅に遅いため、 大量のSwap In / Swap Outが発生するとシステム性能が急激に低下する可能性がある。

そのため「メモリ使用率が高い」という数値だけではなく、 SwapやPage Faultの状態まで確認することが重要となる。


7. LinuxのPage Cache

Linuxは空いているRAMを積極的にPage Cacheとして利用する。

一度ストレージから読み込んだデータをメモリ上に保持することで、 次回以降のアクセスを高速化できる。


Application
     ↓
Page Cache ── HIT ──→ 高速
     ↓ MISS
Storage

このためLinuxでは、単純に「メモリ使用率が90%だから危険」と判断することはできない。

利用可能メモリ、キャッシュ、Swap、アプリケーションのResident Memoryなどを 総合的に確認する必要がある。


8. I/OとI/O Wait

CPUが高速でも、ストレージやネットワークからデータが届かなければ処理を進められない。

このようなI/O性能は、サーバ全体の性能を左右する重要な要素である。

■ I/O性能を見る主要指標

  • IOPS:1秒あたりのI/O処理回数
  • Throughput:単位時間あたりのデータ転送量
  • Latency:I/O完了までの時間
  • Queue Depth:I/O要求の待ち行列

CPU使用率が低いにもかかわらずアプリケーションが遅い場合、 ストレージI/Oがボトルネックになっている可能性がある。


9. CPU BoundとI/O Boundを見極める

■ CPU Bound

CPU計算能力がボトルネックになっている状態。

  • 画像処理
  • 暗号化
  • 圧縮処理
  • 大規模な計算処理

■ I/O Bound

ストレージ・ネットワーク・データベースなどのI/O待ちが ボトルネックになっている状態。

  • 大量ファイルアクセス
  • DBアクセス
  • 外部API通信
  • ネットワーク通信

性能問題を解決する際には、まずCPU BoundなのかI/O Boundなのかを切り分けることが重要である。


10. Linux性能解析ツール

Linuxには、内部状態を観測するためのさまざまなツールが存在する。

■ top / htop


top

CPU・メモリ・プロセス状態を確認する。

■ vmstat


vmstat 1

CPU、メモリ、Run Queue、Swapなどを確認する。

■ iostat


iostat -xz 1

ストレージI/Oの状態を確認する。

■ pidstat


pidstat 1

プロセス単位でCPU・I/Oなどを分析する。

■ strace


strace -p <PID>

プロセスが実行しているシステムコールを追跡する。

例えばアプリケーションが停止しているように見える場合でも、 straceによってread()やconnect()などの待機状態を確認することで、 原因をさらに深いレイヤーまで追跡できる。


11. USE Methodによる性能分析

性能問題を闇雲に調査するのではなく、 体系的に切り分けるための考え方としてUSE Methodがある。

  • Utilization:リソースがどれだけ使用されているか
  • Saturation:処理待ちが発生しているか
  • Errors:エラーが発生しているか

CPU、メモリ、ストレージ、ネットワークなど、 主要リソースについてこの3つの観点から調査する。


CPU
 ├─ Utilization
 ├─ Saturation
 └─ Errors

Memory
 ├─ Utilization
 ├─ Saturation
 └─ Errors

Storage
 ├─ Utilization
 ├─ Saturation
 └─ Errors

Network
 ├─ Utilization
 ├─ Saturation
 └─ Errors

このような調査順序を持つことで、 「なんとなくCPUやメモリを見る」状態から脱却できる。


12. 障害解析の実践シナリオ

例えば「Web APIのレスポンスが突然遅くなった」という障害を考える。

調査では以下のようにレイヤーを分解する。

  1. CPU使用率とRun Queueを確認
  2. メモリ・Swap・Page Faultを確認
  3. ディスクI/OとI/O Waitを確認
  4. ネットワーク状態を確認
  5. 対象プロセスを特定
  6. システムコールやアプリケーションログを確認
  7. DBや外部サービスなど依存先を確認

重要なのは、最初から原因を決めつけないことである。

観測データから仮説を立て、 レイヤーを一つずつ切り分けながら原因を特定することが、 高度なインフラトラブルシューティングの基本となる。


13. 応用エンジニアに必要な性能設計思考

応用レベルでは、「サーバが遅い」という表現だけでは不十分である。

例えば以下のように説明できる必要がある。

  • CPUが飽和しRun Queueが増加している
  • 大量のMajor Page Faultによってストレージアクセスが発生している
  • Swapによってメモリアクセス性能が低下している
  • ストレージLatencyの増大によってI/O待ちが発生している
  • システムコールの待機によってアプリケーション処理が停滞している

つまり、監視値を見るだけではなく、 「OS内部で何が起きた結果、その監視値になったのか」を説明する能力が重要となる。


まとめ

本章では、Linuxサーバの内部挙動と性能解析について学習した。

  • User SpaceとKernel Spaceの境界を理解する
  • システムコールによるOSとの通信を理解する
  • CPUスケジューリングとLoad Averageを正しく解釈する
  • 仮想メモリ・Page Fault・Swapの仕組みを理解する
  • Page CacheとLinuxメモリ管理を理解する
  • CPU BoundとI/O Boundを切り分ける
  • Linuxツールを組み合わせて性能問題を分析する
  • USE Methodによって体系的にボトルネックを特定する

これにより、Linuxサーバを単に操作するだけではなく、 カーネル・CPU・メモリ・I/Oの内部挙動から性能問題を分析できる基盤が整った。

インフラ応用編では、このレベルを出発点として、 分散システム、ネットワーク性能、データベース内部構造、 高可用性、障害解析など、より高度なシステム設計へ進んでいく。