EVENTFD(2) | Linux Programmer's Manual | EVENTFD(2) |
名前
eventfd -イベント通知用のファイルディスクリプタを生成する書式
#include <sys/eventfd.h>説明
eventfd() は "eventfd オブジェクト"を生成する。 eventfd オブジェクトはユーザ空間アプリケーションがイベント待ち受け/通知用の仕組みとして使うことができる。また、カーネルがユーザ空間アプリケーションにイベントを通知するためにも使うことができる。このオブジェクトには、unsigned の 64 ビット整数 ( uint64_t) 型のカウンタが含まれており、このカウンタはカーネルにより管理される。このカウンタは initval 引き数で指定された値で初期化される。- EFD_CLOEXEC (Linux 2.6.27 以降)
- 新しいファイルディスクリプタに対して close-on-exec ( FD_CLOEXEC) フラグをセットする。このフラグが役に立つ理由については、 open(2) の O_CLOEXEC フラグの説明を参照のこと。
- EFD_NONBLOCK (Linux 2.6.27 以降)
- 新しく生成されるオープンファイル記述 (open file description) の O_NONBLOCK ファイルステータスフラグをセットする。このフラグを使うことで、 O_NONBLOCK をセットするために fcntl(2) を追加で呼び出す必要がなくなる。
- EFD_SEMAPHORE (Linux 2.6.30 以降)
- 新しいファイルディスクリプタからの読み出しにおいて、セマフォ風の動作を行う。下記参照。
バージョン 2.6.26 以前の Linux では、 flags 引き数は未使用であり、0 を指定しなければならない。
eventfd() は eventfd オブジェクトを参照するのに使用できる新しいファイルディスクリプタを返す。返されたファイルディスクリプタに対しては以下の操作を実行できる。
- read(2)
- read(2) は成功すると、8 バイトの整数を返す。渡されたバッファの大きさが 8 バイト未満の場合、 read(2) はエラー EINVAL で失敗する。
- read(2) が返す値は、ホストバイトオーダ、つまりそのホストマシンにおける整数の通常のバイトオーダである。
- read(2) の動作は、 eventfd カウンタの現在の値が 0 以外であるかと、 eventfd ファイルディスクリプタを作成する際に EFD_SEMAPHORE フラグが指定されたか、により変化する。
- *
- EFD_SEMAPHORE が指定されておらず、eventfd カウンタが 0 以外の値の場合、 read(2) はカウンタ値を格納した 8 バイトの値を返し、カウンタ値は 0 にリセットされる。
- *
- EFD_SEMAPHORE が指定されていて eventfd カウンタが 0 以外の値の場合、 read(2) は値 1 の 8 バイト値を返し、カウンタ値は 1 減算される。
- *
- read(2) を呼び出した時点で eventfd カウンタが 0 の場合、 read(2) はカウンタが 0 以外になるまで停止 (block) する (0 以外になった時点で read(2) は上記で述べた通り実行を再開する)、もしくはファイルディスクリプタが非停止 (nonblocking) に設定されている場合はエラー EAGAINで失敗する。
- write(2)
- write(2) は、引き数のバッファで渡された 8 バイトの整数値をカウンタに加算する。カウンタに格納可能な最大値は unsigned の 64 ビット整数の最大値から 1 を引いた値 (すなわち 0xfffffffffffffffe) である。加算を行うとカウンタ値が最大値を超過する場合には、そのファイルディスクリプタに対して read(2) が実行されるまで、 write(2) は停止 (block) する、もしくはファイルディスクリプタが非停止 (nonblocking) に設定されている場合はエラー EAGAIN で失敗する。
- 渡されたバッファの大きさが 8 バイト未満の場合、もしくは値 0xffffffffffffffff を書き込もうとした場合、 write(2) はエラー EINVAL で失敗する。
- poll(2), select(2) (と同様の操作)
- 返されたファイルディスクリプタは、 poll(2) ( epoll(7) も同じ) や select(2) をサポートしており、以下のような動作をする。
- *
- カウンタが 0 より大きい値の場合、ファイルディスクリプタは読み出し可能となる ( select(2) の readfds 引き数や poll(2) の POLLIN フラグ)。
- *
- 少なくとも値 "1"を、停止 (block) を伴わずに書き込める場合、ファイルディスクリプタは書き込み可能となる ( select(2) の writefds 引き数や poll(2) の POLLOUT フラグ)。
- *
- カウンタ値のオーバーフローが検出された場合、 select(2) はファイルディスクリプタは読み出し可能と書き込み可能の両方を通知し、 poll(2) は POLLERR イベントを返す。上述の通り、 write(2) でカウンタがオーバーフローすることは決してない。しかしながら、 KAIO サブシステムによって 2^64 回の eventfd "signal posts"が実行された場合にはオーバーフローが起こり得る (理論的にはあり得るが、実用的にはあり得ない)。オーバーフローが発生した場合、 read(2) は uint64_t の最大値 (すなわち 0xffffffffffffffff) を返す。
- eventfd ファイルディスクリプタは、これ以外のファイルディスクリプタ多重 API である pselect(2) と ppoll(2) もサポートしている。
- close(2)
- ファイルディスクリプタがそれ以降は必要なくなった際には、クローズすべきである。同じ eventfd オブジェクトに関連付けられたファイルディスクリプタが全てクローズされると、そのオブジェクト用の資源がカーネルにより解放される。
fork(2) で生成された子プロセスは、 eventfd() で生成されたファイルディスクリプタのコピーを継承する。複製されたファイルディスクリプタは同じ eventfd オブジェクトに関連付けられる。 close-on-exec フラグが設定されていない場合、 execve(2) の前後で eventfd() で生成されたファイルディスクリプタは保持される。
返り値
成功すると、 eventfd() は新規の eventfd ファイルディスクリプタを返す。エラーの場合、-1 を返し、 errno にエラーを示す値を設定する。エラー
- EINVAL
- flags にサポートされていない値が指定された。
- EMFILE
- オープン済みのファイルディスクリプタの数がプロセスあたりの上限に達していた。
- ENFILE
- オープン済みのファイル総数がシステム全体の上限に達していた。
- ENODEV
- (カーネル内の) 無名 inode デバイスをマウントできなかった。
- ENOMEM
- 新しい eventfd ファイルディスクリプタを生成するのに十分なメモリがなかった。
バージョン
eventfd() はカーネル 2.6.22 以降の Linux で利用可能である。正しく動作する glibc 側のサポートはバージョン 2.8 以降で提供されている。 eventfd2() システムコール (「注意」参照) はカーネル 2.6.27 以降の Linux で利用可能である。バージョン 2.9 以降では、glibc の eventfd() のラッパー関数は、カーネルが対応していれば eventfd2() システムコールを利用する。準拠
eventfd() と eventfd2() は Linux 固有である。注意
アプリケーションは、パイプをイベントを通知するためだけに使用している全ての場面において、パイプの代わりに eventfd ファイルディスクリプタを使用することができる。 eventfd ファイルディスクリプタを使う方が、パイプを使う場合に比べてカーネルでのオーバヘッドは比べるとずっと小さく、ファイルディスクリプタも一つしか必要としない (パイプの場合は二つ必要である)。下層にある Linux のシステムコール
下層にある Linux システムコールは二種類あり、 eventfd() と、もっと新しい eventfd2() である。 eventfd() は flags 引き数を実装していない。 eventfd2() では上記の値の flags が実装されている。 glibc のラッパー関数は、 eventfd2() が利用可能であれば、これを使用する。glibc の追加機能
GNU C ライブラリは、eventfd ファイルディスクリプタの読み出しと書き込みにを関する詳細のいくつか抽象化するために、一つの型と、二つの関数を追加で定義している。
typedef uint64_t eventfd_t;
int eventfd_read(int fd, eventfd_t *value);
int eventfd_write(int fd, eventfd_t value);
これらの関数は、eventfd ファイルディスクリプタに対する読み出しと書き込みの操作を実行し、正しいバイト数が転送された場合には 0 を返し、そうでない場合は-1 を返す。
例
以下のプログラムは eventfd ファイルディスクリプタを生成し、その後 fork を実行して子プロセスを生成する。親プロセスが少しの間 sleep する間に、子プロセスはプログラムのコマンドライン引き数で指定された整数(列)をそれぞれ eventfd ファイルディスクリプタに書き込む。親プロセスは sleep を完了すると eventfd ファイルディスクリプタから読み出しを行う。
$ ./a.out 1 2 4 7 14
Child writing 1 to efd
Child writing 2 to efd
Child writing 4 to efd
Child writing 7 to efd
Child writing 14 to efd
Child completed write loop
Parent about to read
Parent read 28 (0x1c) from efd
プログラムのソース
#include <sys/eventfd.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h> /* Definition of uint64_t */
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int
main(int argc, char *argv[])
{
int efd, j;
uint64_t u;
ssize_t s;
if (argc < 2) {
fprintf(stderr, "Usage: %s <num>...\n", argv[0]);
exit(EXIT_FAILURE);
}
efd = eventfd(0, 0);
if (efd == -1)
handle_error("eventfd");
switch (fork()) {
case 0:
for (j = 1; j < argc; j++) {
printf("Child writing %s to efd\n", argv[j]);
u = strtoull(argv[j], NULL, 0);
/* strtoull() allows various bases */
s = write(efd, &u, sizeof(uint64_t));
if (s != sizeof(uint64_t))
handle_error("write");
}
printf("Child completed write loop\n");
exit(EXIT_SUCCESS);
default:
sleep(2);
printf("Parent about to read\n");
s = read(efd, &u, sizeof(uint64_t));
if (s != sizeof(uint64_t))
handle_error("read");
printf("Parent read %llu (0x%llx) from efd\n",
(unsigned long long) u, (unsigned long long) u);
exit(EXIT_SUCCESS);
case -1:
handle_error("fork");
}
}
関連項目
futex(2), pipe(2), poll(2), read(2), select(2), signalfd(2), timerfd_create(2), write(2), epoll(7), sem_overview(7)この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.51 の一部である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。2010-08-30 | Linux |