コース一覧
OS入門:プロセス・メモリ・ファイルシステム
イベントループと epoll

OS入門:プロセス・メモリ・ファイルシステム

OSがCPU・メモリ・ストレージをどのように管理しているかを、プロセス、スレッド、仮想メモリ、ファイルシステム、同期と並行性から体系的に学びます。アプリケーションの裏側で何が起きているかを説明できるようになります。

1
OS とは
0. コンピューターとOSの役割15分
1. OSの歴史(バッチ→マルチタスク→マルチユーザー)15分
2. カーネルとユーザーランド15分
3. システムコールの仕組み15分
4. Linux / macOS / Windows のアーキ比較15分
2
プロセスとスレッド
0. プロセスとは15分
1. スレッドとプロセスの違い15分
2. コンテキストスイッチ15分
3. スケジューラとアルゴリズム15分
4. プロセス間通信(IPC)15分
3
メモリ管理
0. メモリ階層(レジスタ→キャッシュ→RAM→ディスク)15分
1. 仮想メモリ15分
2. ページングとスワップ15分
3. mmap とメモリマップトファイル15分
4. ガベージコレクション概要15分
4
ファイルシステム
0. ファイルシステムとは15分
1. i-node とディレクトリ15分
2. ext4 / APFS / NTFS の違い15分
3. ジャーナリングと耐障害性15分
4. パーミッションと所有者15分
5
同期と並行性
0. レースコンディション15分
1. Mutex と Semaphore15分
2. デッドロック15分
3. 非同期と並行15分
4. イベントループと epoll15分

OS入門:プロセス・メモリ・ファイルシステム

01コンピューターとOSの役割
02OSの歴史(バッチ→マルチタスク→マルチユーザー)
03カーネルとユーザーランド
04システムコールの仕組み
05Linux / macOS / Windows のアーキ比較
06プロセスとは
07スレッドとプロセスの違い
08コンテキストスイッチ
09スケジューラとアルゴリズム
10プロセス間通信(IPC)
11メモリ階層(レジスタ→キャッシュ→RAM→ディスク)
12仮想メモリ
13ページングとスワップ
14mmap とメモリマップトファイル
15ガベージコレクション概要
16ファイルシステムとは
17i-node とディレクトリ
18ext4 / APFS / NTFS の違い
19ジャーナリングと耐障害性
20パーミッションと所有者
21レースコンディション
22Mutex と Semaphore
23デッドロック
24非同期と並行
25イベントループと epoll

OS入門:プロセス・メモリ・ファイルシステム

イベントループと epoll

1 万本の接続のうち、どれに返事が来たのか

前回、1 スレッドのまま数万件を抱えられる、と書きました。ではその 1 スレッドは、どの接続に返事が来たのかをどうやって知るのでしょうか。

普通の read は、データが届くまでその場で待ちます。接続 1 番に対して read を呼んだらそこで止まってしまい、たまたま先にデータが届いた 5,000 番には手が回りません。1 スレッドで多数を見張るには、「今読める接続はどれか」をまとめて教えてもらう別の仕組みが要ります。

全員に聞いて回る方式は、数が増えると潰れる

古くからあるのが select と poll です。監視したい接続の一覧をカーネルへ渡し、この中で読めるようになったものはあるかと尋ねます。

素直な作りですが、呼ぶたびに一覧を丸ごと渡し、カーネルは全部を確認し、戻ってきたアプリ側も全部を走査してどれが立ったのかを調べます。接続が 10 個なら誰も気にしません。10 万個になると、実際に届いたのが 100 件でも、毎回 10 万件を確認することになります。1990 年代末に同時 1 万接続が壁として語られた C10K 問題は、ここが原因でした。

先に登録しておいて、起きた分だけ受け取る

Linux の epoll は順序を入れ替えます。監視したい接続は最初に 1 回だけ登録し、以降は「何か起きたものだけ」を受け取ります。

c

int epfd = epoll_create1(0);
epoll_ctl(epfd, EPOLL_CTL_ADD, sock, &ev);   // 登録は接続ごとに 1 回だけ

while (1) {
    int n = epoll_wait(epfd, events, 100, -1);   // 起きたものだけ n 件返る
    for (int i = 0; i < n; i++)
        handle(events[i].data.fd);
}

10 万接続のうち動いているのが 100 件なら、ループは 100 回しか回りません。1 周の重さが監視数ではなく発生件数に比例するので、接続をいくら増やしても重くなりません。

diagram (will load when visible)

同じ発想の仕組みは各 OS にあり、macOS と BSD では kqueue、Windows では IOCP と呼ばれます。前回の asyncio も、Node.js も nginx も、内側ではこの登録と受け取りを回し続けているだけです。

1 周が長くなると、全員が待たされる

この構造は、ループを止めずに回し続けられることが前提です。取り出した 1 件の処理に 500 ミリ秒かかると、その間は次の受け取りに戻れず、残りの接続は放置されます。

だからイベントループの上には、重い計算も、返るまで待つ形のライブラリ呼び出しも置けません。前回の「別スレッドへ逃がす」がここでも効いてきます。1 件あたりの処理が短いことがそのまま全体のスループットになる、という制約と引き換えに、1 スレッドで 1 万接続が成り立っています。

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • スレッド1 つの質問に紐づく返信の集まり
  • カーネルOS の中核。資源管理を担う
  • ループ繰り返し処理。矢印で戻すか専用記号で示す
  • Node.jsJavaScript をサーバ側で動かすランタイム
  • 処理計算や代入を表す長方形
  • イベントループI/O 待ちで他処理を回す機構
  • イベントユーザーの操作(クリック、入力、スクロール等)を検知して処理を実行する仕組み。
生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/05/27·更新 2026/08/26

関連レッスン

  • 非同期と並行

    並行と並列の違い、I/O 待ちの間に他の仕事を進める非同期処理の考え方を、コールバックから async/await への進化とあわせて初学者にも分かる形で解説します。

  • デッドロック

    複数スレッドが互いのロックを待ち合って永久停止するデッドロックの成立条件と、ロック順序の固定やタイムアウトなど複数の防止策を実務目線で解説します。

  • Mutex と Semaphore

    同時に一つしか入れない Mutex と、N 個まで入れる Semaphore の違いを、所有権の概念と具体的な使いどころを示しながら分かりやすく整理します。

  • レースコンディション

    複数スレッドが同じ資源を同時に変更し実行順で結果が変わるレースコンディションの正体と、アトミック操作やロックで防ぐ具体策を実務目線で解説します。

分からないところは Tap (AI先生) に質問できます

24 時間いつでも、あなたのレベルに合わせて日本語で答えます。