コンピューターサイエンス:アルゴリズム / OS / ネットワーク / DB

システムコールの仕組み

生田 陸人
LuaGate エンジニア / 現役エンジニア
編集 LuaGate編集部

システムコールの仕組み

このレッスンで分かること

  • システムコールはユーザープロセスがカーネルに 特定の処理を依頼する唯一の正規ルート です
  • 内部では CPU の特権レベルが切替わり、引数はレジスタ経由でカーネルに渡されます
  • read write open fork execve などおなじみの関数は、すべてシステムコールの薄いラッパーです

システムコールの仕組み とは

システムコールの仕組み。本レッスンでは、システムコールの仕組み の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

システムコールとは

ユーザー空間のプロセスは自分のメモリしか触れません。ファイルを読みたい、新しいプロセスを作りたい、ソケットを開きたい――どれもカーネルにしかできない仕事です。そこでユーザープロセスは「お願いごと」をカーネルに渡す手段が必要になります。これがシステムコールです。

Linux の man 2 syscalls を覗くと、約 400 個のシステムコールが定義されています。readwriteopencloseforkexecvemmapsocket などです。これら以外の方法でカーネルに介入することはできません(モジュールローディング等の特権操作はあるが、それもシステムコール経由)。

呼び出しの流れ

diagram (will load when visible)

ユーザー空間 → syscall 命令で CPU がトラップ → カーネル空間 → 処理 → 結果を返却、という流れです。CPU の特権切替えはハードウェアレベルの仕組みで、攻撃者がカーネルに自由に侵入することを防ぎます。

具体例

C で write(1, "hi\n", 3) を呼んだときの引数渡しを見てみましょう。x86_64 Linux では次のように決められています。

レジスタ役割例(write の場合)
raxシステムコール番号1(write)
rdi第 1 引数1(標準出力 fd)
rsi第 2 引数バッファのアドレス
rdx第 3 引数3(バイト数)
rax(戻り値)結果書き込めたバイト数

アセンブリで書くと下記のようになります。

asm

mov rax, 1 ; write のシステムコール番号 mov rdi, 1 ; fd = stdout mov rsi, msg ; メッセージのアドレス mov rdx, 3 ; 長さ syscall ; カーネルに突入

Python の print("hi") も、最終的にはこの流れに行き着きます。

トレースしてみる

strace コマンドを使うと、プログラムが呼んでいるシステムコールがすべて見えます。

ターミナル

strace -e openat,read,write echo hello

出力例の抜粋は下記のとおりです。

プレーンテキスト

openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 read(3, "...", 832) = 832 write(1, "hello\n", 6) = 6

echo 1 つのために、共有ライブラリ読み込みなど多数のシステムコールが発行されていることが分かります。

トレードオフ

  • システムコールは 数百 ナノ秒 ~ 数 マイクロ秒 のコストがかかります。1 バイトずつ write を呼ぶより、4KB バッファに溜めて 1 回呼ぶ方が桁違いに速いのはこのためです
  • io_uring(2019, Linux 5.1) は「複数のシステムコールをまとめて投入し、結果を別途取り出す」仕組みで、高負荷ネットワークサーバーの性能を改善しました
  • セキュリティ対策の Spectre/Meltdown パッチ(KPTI)が入ってから、システムコール 1 回あたりのコストが体感で 1.5 倍程度に増えました

よくある誤解

  • 「ライブラリ関数 = システムコール」ではありません。malloc printf sin などは libc 内部で完結 し、システムコールを呼ばないケースが多いです
  • 「fork() は関数」と思いがちですが、その正体は clone システムコールへの薄いラッパーです

やってみよう

strace -c ./your-program を実行し、どのシステムコールが何回呼ばれているかの集計を見てください。futexbrkmmap が頻発しているなら、メモリ確保や同期処理がボトルネックの可能性があります。

よくある質問

Q. このトピックは実務でどう役立ちますか?

A. DB のクエリ最適化、API 設計、データ構造の選択など、設計判断の根拠になります。表面的にライブラリを使うだけでなく「なぜそれが速いのか」を理解できると、性能問題を未然に防げます。コーディング面接でも頻出のテーマです。

Q. 計算量はどう求めれば良いですか?

A. ループのネストごとに掛け算する、再帰なら漸化式から解く、というのが基本です。Big-O 表記は定数倍と低次の項を無視するため、n の指数(n²、n log n など)に注目してください。最悪・平均・最良の 3 つを意識すると説得力が増します。

Q. 覚えるべき定番アルゴリズムは何ですか?

A. 二分探索、クイックソート/マージソート、BFS/DFS、ダイクストラ、DP の基本問題(フィボナッチ・ナップサック)が必修です。これらを「白紙から書ける」状態にすると、応用問題が一気に解けるようになります。

次のレッスン

次は Linux / macOS / Windows のアーキ比較 で、システムコールの仕組み を学びます。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. システムコール の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. システムコール とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン