# epoll
## 定義
**epoll** は Linux カーネルが提供するスケーラブルな I/O イベント通知機構である。大量のファイル記述子を監視しながら、ready になった記述子だけを O(1) で返す。`select()`・`poll()` の O(n) スキャン問題を解決し、[[C10K問題]] への Linux の回答として位置づけられる。
## 歴史
- **2001年7月11日** — Davide Libenzi が Linux カーネルメーリングリストに `/dev/epoll` として提案(リアルタイムシグナルの代替)。
- Linux 2.5.x でインターフェースが特殊ファイル(`/dev/epoll`)から `sys_epoll` システムコールへ変更。
- **Linux 2.5.46** — メインラインカーネルへマージ。
- Linux 2.4 向けのバックポートパッチも提供された。
## API
```c
// epoll インスタンス作成
int epfd = epoll_create(size); // size はヒント(Linux 2.6.8 以降は無視)
// 監視対象を追加/変更/削除
struct epoll_event ev = {
.events = EPOLLIN | EPOLLET, // EPOLLET でエッジトリガ
.data.fd = sockfd
};
epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev);
// イベント待機(タイムアウト ms; -1 は無限)
struct epoll_event events[MAX_EVENTS];
int n = epoll_wait(epfd, events, MAX_EVENTS, timeout_ms);
```
## レベルトリガとエッジトリガ
- **レベルトリガ(デフォルト)** — データが残っている限り毎回通知。`select()`/`poll()` と同等の意味論。
- **エッジトリガ(`EPOLLET`)** — not-ready→ready への遷移時のみ通知。見落とし厳禁だが、同一記述子の重複通知がなくスケーラブル。
エッジトリガ使用時は `EAGAIN`/`EWOULDBLOCK` が返るまで read/write を繰り返す必要がある。
## select/poll との比較
| 項目 | select | poll | epoll |
|-----|--------|------|-------|
| 上限 | FD_SETSIZE(1024) | なし | `/proc/sys/fs/nr_open` |
| スキャン | O(n) | O(n) | O(1) |
| カーネルへの再登録 | 毎回 | 毎回 | 変更時のみ |
| エッジトリガ | なし | なし | あり(EPOLLET) |
## 現代の利用
[[nginx]]・libuv(Node.js)・Tokio(Rust)・asyncio(Python)・Java NIO(epoll ベース)が Linux 上でバックエンドとして epoll を使用している。[[kqueue]] は BSD/macOS 向けの対応機構。
## 関連
- [[C10K問題]] — epoll が解決した問題
- [[kqueue]] — BSD 向けの相当機構
- [[Davide Libenzi]] — 提案者
- [[nginx]] — epoll を活用した代表的サーバ