名 前
eventfd − イ ベ ン ト 通 知 用 の フ ァ イ ル デ ィ ス ク リ プ タ ー を 生 成 す る
書 式
#include <sys/eventfd.h>
int eventfd(unsigned int initval, int flags);
説 明
eventfd()
は "eventfd オ ブ ジ ェ
ク ト " を 生 成 す
る 。 eventfd オ ブ ジ
ェ ク ト は ユ ー
ザ ー 空 間 ア プ
リ ケ ー シ ョ ン
が イ ベ ン ト 待
ち 受 け /通 知 用
の 仕 組 み と し
て 使 う こ と が
で き る 。 ま た
、 カ ー ネ ル が
ユ ー ザ ー 空 間
ア プ リ ケ ー シ
ョ ン に イ ベ ン
ト を 通 知 す る
た め に も 使 う
こ と が で き る
。 こ の オ ブ ジ
ェ ク ト に は 、
unsigned の 64 ビ ッ ト 整
数 (uint64_t) 型 の カ
ウ ン タ ー が 含
ま れ て お り 、
こ の カ ウ ン タ
ー は カ ー ネ ル
に よ り 管 理 さ
れ る 。 こ の カ
ウ ン タ ー は initval
引 き 数 で 指 定
さ れ た 値 で 初
期 化 さ れ る 。
以 下 の 値 の い
く つ か を ビ ッ
ト 単 位 の 論 理
和 (OR) で 指 定 す る
こ と で 、 eventfd()
の 振 舞 い を 変
更 す る こ と が
で き る 。
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) は 、 引 き 数 の バ ッ フ ァ ー で 渡 さ れ た 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 フ ラ グ )。
* カ ウ ン タ ー 値 の オ ー バ ー フ ロ ー が 検 出 さ れ た 場 合 、 |
フ ァ イ ル デ ィ ス ク リ プ タ ー は 読 み 出 し 可 能 と 書 き 込 み 可 能 の 両 方 を 通 知 し 、 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 フ ァ イ ル デ ィ ス ク リ プ タ ー を 使 う 方 が 、 パ イ プ を 使 う 場 合 に 比 べ て カ ー ネ ル で の オ ー バ ヘ ッ ド は 比 べ る と ず っ と 小 さ く 、 フ ァ イ ル デ ィ ス ク リ プ タ ー も 一 つ し か 必 要 と し な い (パ イ プ の 場 合 は 二 つ 必 要 で あ る )。 カ ー ネ ル 内 で 使 用 す る と 、 eventfd フ ァ イ ル デ ィ ス ク リ プ タ ー は カ ー ネ ル 空 間 か ら ユ ー ザ ー 空 間 へ の ブ リ ッ ジ 機 能 を 提 供 す る こ と が で き 、 例 え ば KAIO (kernel AIO) の よ う な 機 能 が 、 あ る フ ァ イ ル デ ィ ス ク リ プ タ ー に 何 ら か の 操 作 が 完 了 し た こ と を 通 知 す る こ と が で き る 。
eventfd フ ァ イ ル デ ィ ス ク リ プ タ ー の 重 要 な 点 は 、 eventfd フ ァ イ ル デ ィ ス ク リ プ タ ー が select(2), poll(2), epoll(7) を 使 っ て 他 の フ ァ イ ル デ ィ ス ク リ プ タ ー と 全 く 同 様 に 監 視 で き る 点 で あ る 。 こ の こ と は 、 ア プ リ ケ ー シ ョ ン は 「 従 来 の (traditional)」 フ ァ イ ル の 状 態 変 化 と eventfd イ ン タ ー フ ェ ー ス を サ ポ ー ト す る 他 の カ ー ネ ル 機 構 の 状 態 変 化 を 同 時 に 監 視 で き る こ と を 意 味 す る (eventfd() イ ン タ ー フ ェ ー ス が な い 時 に は 、 こ れ ら の カ ー ネ ル 機 構 は select(2), poll(2), epoll(7) 経 由 で 多 重 す る こ と は で き な か っ た )。
C ラ イ ブ ラ リ と カ ー ネ ル ABI の 違 い 下 層 に あ る 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.79 の 一 部 で あ る 。 プ ロ ジ ェ ク ト の 説 明 と バ グ 報 告 に 関 す る 情 報 は http://www.kernel.org/doc/man−pages/ に 書 か れ て い る 。