コンピューターサイエンス:アルゴリズム / OS / ネットワーク / DB
システムコールの仕組み
システムコールの仕組み
このレッスンで分かること
- システムコールはユーザープロセスがカーネルに 特定の処理を依頼する唯一の正規ルート です
- 内部では CPU の特権レベルが切替わり、引数はレジスタ経由でカーネルに渡されます
readwriteopenforkexecveなどおなじみの関数は、すべてシステムコールの薄いラッパーです
システムコールの仕組み とは
システムコールの仕組み。本レッスンでは、システムコールの仕組み の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。
システムコールとは
ユーザー空間のプロセスは自分のメモリしか触れません。ファイルを読みたい、新しいプロセスを作りたい、ソケットを開きたい――どれもカーネルにしかできない仕事です。そこでユーザープロセスは「お願いごと」をカーネルに渡す手段が必要になります。これがシステムコールです。
Linux の man 2 syscalls を覗くと、約 400 個のシステムコールが定義されています。read、write、open、close、fork、execve、mmap、socket などです。これら以外の方法でカーネルに介入することはできません(モジュールローディング等の特権操作はあるが、それもシステムコール経由)。
呼び出しの流れ
ユーザー空間 → 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) = 6echo 1 つのために、共有ライブラリ読み込みなど多数のシステムコールが発行されていることが分かります。
トレードオフ
- システムコールは 数百 ナノ秒 ~ 数 マイクロ秒 のコストがかかります。1 バイトずつ
writeを呼ぶより、4KB バッファに溜めて 1 回呼ぶ方が桁違いに速いのはこのためです io_uring(2019, Linux 5.1) は「複数のシステムコールをまとめて投入し、結果を別途取り出す」仕組みで、高負荷ネットワークサーバーの性能を改善しました- セキュリティ対策の Spectre/Meltdown パッチ(KPTI)が入ってから、システムコール 1 回あたりのコストが体感で 1.5 倍程度に増えました
よくある誤解
- 「ライブラリ関数 = システムコール」ではありません。
mallocprintfsinなどは libc 内部で完結 し、システムコールを呼ばないケースが多いです - 「fork() は関数」と思いがちですが、その正体は
cloneシステムコールへの薄いラッパーです
やってみよう
strace -c ./your-program を実行し、どのシステムコールが何回呼ばれているかの集計を見てください。futex、brk、mmap が頻発しているなら、メモリ確保や同期処理がボトルネックの可能性があります。
よくある質問
Q. このトピックは実務でどう役立ちますか?
A. DB のクエリ最適化、API 設計、データ構造の選択など、設計判断の根拠になります。表面的にライブラリを使うだけでなく「なぜそれが速いのか」を理解できると、性能問題を未然に防げます。コーディング面接でも頻出のテーマです。
Q. 計算量はどう求めれば良いですか?
A. ループのネストごとに掛け算する、再帰なら漸化式から解く、というのが基本です。Big-O 表記は定数倍と低次の項を無視するため、n の指数(n²、n log n など)に注目してください。最悪・平均・最良の 3 つを意識すると説得力が増します。
Q. 覚えるべき定番アルゴリズムは何ですか?
A. 二分探索、クイックソート/マージソート、BFS/DFS、ダイクストラ、DP の基本問題(フィボナッチ・ナップサック)が必修です。これらを「白紙から書ける」状態にすると、応用問題が一気に解けるようになります。
次のレッスン
次は Linux / macOS / Windows のアーキ比較 で、システムコールの仕組み を学びます。
事前確認 — 進む前に次の 3 つができることを確認しましょう。
- システムコール の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. システムコール とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン