Provided by: manpages-ja-dev_0.5.0.0.20221215+dfsg-1_all bug

名前

       eventfd - イベント通知用のファイルディスクリプターを生成する

書式

       #include <sys/eventfd.h>

       int eventfd(unsigned int initval, int flags);

説明

       eventfd()  は "eventfd オブジェクト" を生成する。 eventfd オブジェクトはユーザー空間アプリ
       ケーションがイベント待ち受け/通知用の   仕組みとして使うことができる。また、カーネルがユー
       ザー空間アプリケーションに イベントを通知するためにも使うことができる。 このオブジェクトに
       は、unsigned の 64  ビット整数  (uint64_t)  型のカウンターが含まれており、このカウンターは
       カーネルにより管理される。 このカウンターは initval 引数で指定された値で初期化される。

       eventfd()  は eventfd オブジェクトを参照するのに使用できる新しいファイルディスクリプターを
       返す。

       以下の値のいくつかをビット単位の論理和 (OR) で指定することで、 eventfd()  の振舞いを変更す
       ることができる。

       EFD_CLOEXEC (Linux 2.6.27 以降)
              新しいファイルディスクリプターに対して close-on-exec (FD_CLOEXEC)  フラグをセットす
              る。 このフラグが役に立つ理由については、 open(2)  の O_CLOEXEC  フラグの説明を参照
              のこと。

       EFD_NONBLOCK (Linux 2.6.27 以降)
              Set  the  O_NONBLOCK  file  status  flag on the open file description (see open(2))
              referred to by the new file descriptor.  Using  this  flag  saves  extra  calls  to
              fcntl(2)  to achieve the same result.

       EFD_SEMAPHORE (Linux 2.6.30 以降)
              新しいファイルディスクリプターからの読み出しにおいて、セマフォ風の動作を行う。 下記
              参照。

       バージョン 2.6.26 以前の Linux では、 flags  引数は未使用であり、0  を指定しなければならな
       い。

       The following operations can be performed on the file descriptor returned by 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()  システムコールを利用す
       る。

属性

       この節で使用されている用語の説明については、 attributes(7) を参照。

       ┌─────────────────┬───────────────┬─────────┐
       │インターフェース属性      │
       ├─────────────────┼───────────────┼─────────┤
       │eventfd()        │ Thread safety │ MT-Safe │
       └─────────────────┴───────────────┴─────────┘

準拠

       eventfd()  と eventfd2()  は Linux 固有である。

注意

       アプリケーションは、パイプをイベントを通知するためだけに使用している      全ての場面におい
       て、パイプの代わりに  eventfd  ファイルディスクリプターを  使用することができる。  eventfd
       ファイルディスクリプターを使う方が、パイプを使う場合に比べて  カーネルでのオーバヘッドは比
       べるとずっと小さく、ファイルディスクリプターも  一つしか必要としない (パイプの場合は二つ必
       要である)。

       カーネル内で使用すると、eventfd ファイルディスクリプターはカーネル空間からユーザー空間への
       ブリッジ機能を提供することができ、  例えば KAIO (kernel AIO)  のような機能が、あるファイル
       ディスクリプターに何らかの操作が完了したことを 通知することができる。

       eventfd    ファイルディスクリプターの重要な点は、    eventfd    ファイルディスクリプターが
       select(2), poll(2), epoll(7)  を使って他のファイルディスクリプターと全く同様に監視できる点
       である。   このことは、アプリケーションは「従来の   (traditional)」   ファイルの状態変化と
       eventfd  インターフェースをサポートする他のカーネル機構の状態変化を同時に監視 できることを
       意味する   (eventfd()    インターフェースがない時には、これらのカーネル機構は   select(2),
       poll(2), epoll(7)  経由で多重することはできなかった)。

       The  current value of an eventfd counter can be viewed via the entry for the corresponding
       file descriptor in the process's /proc/[pid]/fdinfo directory.  See proc(5)   for  further
       details.

   C ライブラリとカーネルの違い
       下層にある 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 <inttypes.h>           /* Definition of PRIu64 & PRIx64 */
       #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;
           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 (int 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 %"PRIu64" (%#"PRIx64") from efd\n", u, 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 プロジェクトのリリース 5.10 の一部である。プロジェクトの
       説明とバグ報告に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。