Provided by: manpages-ja_0.5.0.0.20131015+dfsg-2_all
名前
epoll - I/O イベント通知機能
書式
#include <sys/epoll.h>
説明
epoll API は poll(2) と同様の処理を行う、つまり、複数のファイルディスク リプタを監視し、そ の中のいずれかが入出力可能な状態であるかを確認する。 epoll API は、エッジトリガインタ フェースとレベルトリガインタフェースの いずれとしても使用することができ、監視するファイル ディスクリプタの数が多い 場合にも使用できる。 epoll インスタンスの作成や管理を行うために 以下のシステムコールが提供されている: * epoll_create(2) は epoll インスタンスを作成し、そのインスタンスを参照する ファイルディ スクリプタを返す。(もっと新しい epoll_create1(2) では、 epoll_create(2) の機能が拡張さ れている)。 * 特定のファイルディスクリプタに対する監視内容を epoll_ctl(2) で登録する。 epoll インス タンスに現在登録されているファイルディスクリプタの集合は epoll 集合と呼ばれることもあ る。 * epoll_wait(2) は I/O イベントを待つ。 現在利用可能な状態のイベントがなければ、呼び出し たスレッドを停止する。 レベルトリガとエッジトリガ epoll イベント配送 (distribution) インタフェースは、 エッジトリガ (ET) としてもレベルトリ ガ (LT) としても動作させることができる。 二つの配送機構の違いは、次のように説明できる。 こ のようなシナリオが起こったとしよう: 1. パイプの読み込み側を表すファイルディスクリプタ (rfd) が epoll インスタンスに登録され る。 2. パイプへ書き込むプログラムが 2 kB のデータをパイプの書き込み側へ書き込む。 3. epoll_wait(2) を呼び出すと、読み込み可能 (ready) なファイルディスクリプタとして rfd が 返る。 4. パイプから読み出すプログラムが、1 kB のデータを rfd から読み出す。 5. epoll_wait(2) の呼び出しが行われる。 rfd ファイルディスクリプタが EPOLLET フラグ (エッジトリガ) を使って epoll に追加されている と、 利用可能なデータがファイル入力バッファにまだ存在するにもかかわらず ステップ 5 の epoll_wait(2) の呼び出しでハングする可能性がある。 その一方で、リモートの接続先 (peer) は 既に送られたデータに 基づいて応答を期待しているかもしれない。 このようなことが起こる理由 は、エッジトリガイベント配送では、 モニタしているファイルでイベントが起ったときにのみイベ ントが 配送されるためである。 したがって、ステップ 5 では、呼び出し側は結果的に 入力バッ ファ内にすで存在するデータを待つことになるかもしれない。 上記の例では、 2 で行われた書き込 みによって rfd に関するイベントが生成され、 3 でイベントが消費 (consume) される。 4 で行わ れる読み込み操作では、全部のバッファデータを消費しないので、 ステップ 5 で行われる epoll_wait(2) の呼び出しが 無期限に停止 (block) するかもしれない。 EPOLLET フラグを採用するアプリケーションでは、 インタフェースはブロックしない (nonblocking) ファイルディスクリプタを 使うべきである。 これは、ブロックされる読み込みや書 き込みによって、 複数のファイルディスクリプタを扱うタスクが 停止してしまうのを避けるためで ある。 epoll をエッジトリガ (EPOLLET) インタフェースとして使うために提案される方法は以下 の通りである。 i ブロックしないファイルディスクリプタと共に使う。 ii read(2) または write(2) が EAGAIN を返した後でのみ、イベントを待つ。 一方、レベルトリガインタフェースとして使う場合 (こちらがデフォルトである、 EPOLLET が指定されなかった場合)、 epoll は単に高速な poll(2) であり、使い方が同じなので、 poll(2) が使われているところではどこでも使用することができ る。 エッジトリガを使った場合でも、複数のデータを受信すると複数の epoll イベントが生成されるの で、 呼び出し側には EPOLLONESHOT フラグを指定するオプションがある。 このフラグは epoll に 対して、 epoll_wait(2) によるイベントを受信した後で、関連するファイルディスクリプタを無効 にさせる。 EPOLLONESHOT フラグが指定された場合、 epoll_ctl(2) に EPOLL_CTL_MOD を指定して ファイルディスクリプタを再度使用できるようにするのは、 呼び出し側の責任である。 /proc インタフェース epoll が消費するカーネルメモリの量を制限するために、 以下のインタフェースを使用することが できる。 /proc/sys/fs/epoll/max_user_watches (Linux 2.6.28 以降) このファイルは、あるユーザがシステム上の全ての epoll インスタンスに 登録できるファ イルディスクリプタの総数の上限を規定する。 この上限は実ユーザ ID 単位である。 登録 されたファイルディスクリプタ 1 つが消費するメモリ量は、 32 ビットカーネルでおよそ 90 バイト、 64 ビットカーネルでおよそ 160 バイトである。 現在のところ、 max_user_watches のデフォルト値は、利用可能なメモリ下限の 1/25 (4%) であり、 登録で 消費されるメモリ量 (バイト単位) で割った値となる。 おすすめな使用例 レベルトリガインタフェースとして使用するときの epoll の使い方は poll(2) と同じである。 し かしエッジトリガとして使う場合は、 アプリケーションのイベントループでストール (stall) しな いように、 使い方をより明確にしておく必要がある。 この例では、リスナはブロックしないソケッ トであり、 listen(2) が呼ばれている。 関数 do_use_fd() は、 read(2) または write(2) に よって EAGAIN が返されるまでは、新しい準備済みのファイルディスクリプタを使う。 イベント駆 動ステートマシンアプリケーションは、 EAGAIN を受信した後、カレントの状態を記録しておくべき である。 これにより、次の do_use_fd() 呼び出しのときに、以前に停止したところから read(2) または write(2) を継続することができる。 #define MAX_EVENTS 10 struct epoll_event ev, events[MAX_EVENTS]; int listen_sock, conn_sock, nfds, epollfd; /* Set up listening socket, 'listen_sock' (socket(), bind(), listen()) */ epollfd = epoll_create(10); if (epollfd == -1) { perror("epoll_create"); exit(EXIT_FAILURE); } ev.events = EPOLLIN; ev.data.fd = listen_sock; if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) { perror("epoll_ctl: listen_sock"); exit(EXIT_FAILURE); } for (;;) { nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); if (nfds == -1) { perror("epoll_pwait"); exit(EXIT_FAILURE); } for (n = 0; n < nfds; ++n) { if (events[n].data.fd == listen_sock) { conn_sock = accept(listen_sock, (struct sockaddr *) &local, &addrlen); if (conn_sock == -1) { perror("accept"); exit(EXIT_FAILURE); } setnonblocking(conn_sock); ev.events = EPOLLIN | EPOLLET; ev.data.fd = conn_sock; if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock, &ev) == -1) { perror("epoll_ctl: conn_sock"); exit(EXIT_FAILURE); } } else { do_use_fd(events[n].data.fd); } } } エッジトリガインタフェースとして使う場合、性能上の理由により、 一度 (EPOLLIN|EPOLLOUT) を 指定してから (EPOLL_CTL_ADD で) ファイルディスクリプタを epoll インタフェースに追加するこ とができる。 これにより、 epoll_ctl(2) に EPOLL_CTL_MOD を指定して呼び出すことで EPOLLIN と EPOLLOUT の連続的な切り替えが避けられる。 質問と解答 Q0 epoll 集合内の登録されたファイルディスクリプタを区別するには、 何をキーとして使えばよ いか? A0 キーはファイルディスクリプタ番号とオープンファイル記述 (open file description) の組で ある (オープンファイル記述は "open file handle" とも 呼ばれ、オープンされたファイルの カーネルの内部表現である)。 Q1 1 つの epoll インスタンスに同じファイルディスクリプタを 2 回登録するとどうなるか? A1 たぶん EEXIST を受け取るだろう。 しかしながら、同じ epoll インスタンスに対して複製され たディスクリプタを追加することは可能である (dup(2), dup2(2), fcntl(2) F_DUPFD など)。 複製したファイルディスクリプタを異なる events マスクで登録すれば、イベントをフィルタリ ングするのに この機能は有用な手法である。 Q2 2 つの epoll インスタンスが同じファイルディスクリプタを待ち受けることは可能か? もし可 能であれば、イベントは両方の epoll ファイルディスクリプタに報告されるか? A2 イベントは両方に報告される。 しかしながら、これを正しく扱うには注意深くプログラミング する必要が あるかもしれない。 Q3 epoll ファイルディスクリプタ自身は poll/epoll/select が可能か? A3 可能である。 epoll ファイルディスクリプタに処理待ちのイベントがある場合は、 読み出し可 能だと通知されることだろう。 Q4 epoll ファイルディスクリプタを自身のファイルディスクリプタ集合に 入れようとするとどう なるか? A4 epoll_ctl(2) の呼び出しは (EINVAL で) 失敗するだろう。 ただし epoll ファイルディスク リプタを他の epoll ファイルディスクリプタ集合の内部に追加することは可能である。 Q5 epoll ファイルディスクリプタを UNIX ドメインソケットで他のプロセスに送ることは可能か? A5 可能だが、これをすることに意味はない。 なぜなら、受信側のプロセスが epoll 集合内のファ イルディスクリプタのコピーを持っていないからである。 Q6 ファイルディスクリプタをクローズすると、そのファイルディスクリプタは全ての epoll 集合 から自動的に削除されるか? A6 削除されるが、以下の点に注意が必要である。 ファイルディスクリプタはオープンファイル記 述 (open(2) 参照) への参照である。 ディスクリプタの複製を dup(2), dup2(2), fcntl(2) の F_DUPFD や fork(2) 経由で行う度に、同じオープンファイル記述を参照する新規のファイル ディスクリプタが生成される。 オープンファイル記述自体は、自身を参照する全てのファイル ディスクリプタ がクローズされるまで存在し続ける。 ファイルディスクリプタが epoll 集合 から削除されるのは、対応するオープンファイル記述を参照している 全てのファイルディスク リプタがクローズされた後である (epoll_ctl(2) EPOLL_CTL_DEL を使ってそのディスクリプタ を明示的に削除した場合にも削除される)。 このことは、 epoll 集合に属しているあるファイ ルディスクリプタをクローズした後であっても、 同じファイル記述を参照する他のファイル ディスクリプタがオープンされている間は、 クローズしたファイルディスクリプタ宛にイベン トが報告される可能性があると いうことを意味する。 Q7 2 つ以上のイベントが epoll_wait(2) コールの間に発生した場合、それらはまとめて報告され るか、 それとも別々に報告されるか? A7 まとめて報告されるだろう。 Q8 ファイルディスクリプタに対する操作は、 既に集められているがまだ報告されていないイベン トに影響するか? A8 既存のファイルディスクリプタに対して 2 つの操作を行うことができる。 この場合、削除には 意味がない。 変更すると、使用可能な I/O が再び読み込まれる。 Q9 EPOLLET フラグ (エッジトリガ動作) を使っている場合、 EAGAIN を受け取るまで、 継続して ファイルディスクリプタを読み書きする必要があるか? A9 epoll_wait(2) からイベントを受け取ることは、 そのファイルディスクリプタが要求された I/O 操作に対して準備済みである、 ということをユーザに示すものである。 次の (ブロックし ない) read/write で EAGAIN を受け取るまではファイルディスクリプタは準備済みであると 考 えなければならない。 そのファイルディスクリプタをいつどのように使うかは、 全くユーザに 任されてる。 パケット指向やトークン指向のファイル (例えば、データグラムソケット、 canonical モード の端末) では、 読み込み用 / 書き込み用の I/O 空間の末尾を検知する唯一の方法は EAGAIN になるまで read/write を行うことである。 ストリーム指向のファイル (例えば、パイプ、FIFO、ストリームソケット) では、 読み込み用 / 書き込み用の I/O 空間が使い尽くされた状態は、 対象となるファイルディスクリプタから読 み込んだデータ量または 書き込んだデータ量をチェックすることでも検知できる。 例えば、あ る特定の量のデータを読み込むために read(2) を呼んだときに、 read(2) が返したバイト数 がそれより少なかった場合、 そのファイルディスクリプタの読み込み用 I/O 空間が 使い尽く されたことが分かる。 write(2) を使って書き込みをするときも、同じことが言える (監視して いるファイルディスクリプタが常にストリーム指向のファイルを 参照していることを保証でき ない場合には、後者の手法の使用を避けること)。 ありがちな落とし穴と回避方法 o 飢餓 (starvation) (エッジトリガ) 大きな I/O 空間がある場合、 その I/O 空間のデータを全て処理 (drain) しようとすると、 他の ファイルが処理されず、飢餓を発生させることがある (この問題は epoll に固有のものではない)。 この問題の解決法は、準備済み状態のリストを管理して、 関連する data 構造体の中でファイル ディスクリプタが 利用可能であるとマークすることである。 それによって、利用可能なすべての ファイルの中で どのファイルを処理する必要があるかを憶えることができ、 しかも順番に処理 (round robin) することができる。 既に利用可能であるファイルディスクリプタに対して それ以後 に受け取るイベントを無視することもできる。 o イベントキャッシュを使っている場合 イベントキャッシュを使っている場合、 または epoll_wait(2) から返された全てのファイルディ スクリプタを格納している場合、 クローズされたことを動的にマークする (つまり前のイベントの 処理によってマークされる) 方法を提供すべきである。 epoll_wait(2) から 100 個のイベントを受 け取り、 イベント #47 ではある条件でイベント #13 が閉じられると仮定する。 イベント #13 の 構造体を削除しファイルディスクリプタを close(2) すると、イベントキャッシュはそのファイル ディスクリプタを待つイベントが 存在するといって、混乱が起きる。 この問題を解決する 1 つの方法は、イベント 47 の処理をしている間に、 ファイルディスクリプタ 13 を削除して close(2) するために epoll_ctl(EPOLL_CTL_DEL) を呼び出し、関連付けられた data 構造体を削除済みとマークして、 クリーンアップリストにリンクすることである。 バッチ処 理の中でファイルディスクリプタ 13 についての 他のイベントを見つけた場合、 そのファイルディ スクリプタが以前に削除されたものであると分かるので、 混乱は起きない。
バージョン
epoll API は Linux カーネル 2.5.44 に導入された。 glibc でのサポートはバージョン 2.3.2 で 追加された。
準拠
epoll API は Linux 固有である。 他のシステムでも同様の機構が提供されている場合がある。 例 えば、FreeBSD の kqueue や Solaris の /dev/poll などである。
関連項目
epoll_create(2), epoll_create1(2), epoll_ctl(2), epoll_wait(2)
この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.54 の一部 である。プロジェクト の説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。