Manpages

名 前

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)

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 フ ァ イ ル デ ィ ス ク リ プ タ ー を 使 う 方 が 、 パ イ プ を 使 う 場 合 に 比 べ て カ ー ネ ル で の オ ー バ ヘ ッ ド は 比 べ る と ず っ と 小 さ く 、 フ ァ イ ル デ ィ ス ク リ プ タ ー も 一 つ し か 必 要 と し な い (パ イ プ の 場 合 は 二 つ 必 要 で あ る )。 カ ー ネ ル 内 で 使 用 す る と 、 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/ に 書 か れ て い る 。