# 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 を活用した代表的サーバ