名 前
timerfd_create, timerfd_settime, timerfd_gettime − フ ァ イ ル デ ィ ス ク リ プ タ ー 経 由 で 通 知 す る タ イ マ ー
書 式
#include <sys/timerfd.h>
int timerfd_create(int clockid, int flags);
int
timerfd_settime(int fd, int
flags,
const struct itimerspec *new_value,
struct itimerspec *old_value);
int timerfd_gettime(int fd, struct itimerspec *curr_value);
説 明
こ れ ら の シ ス テ ム コ ー ル は 、 満 了 通 知 を フ ァ イ ル デ ィ ス ク リ プ タ ー 経 由 で 配 送 す る タ イ マ ー の 生 成 と 操 作 を 行 う 。 こ れ ら は 、 setitimer(2) や timer_create(2) を 用 い る 方 法 の 代 わ り と な る も の で あ り 、 こ の フ ァ イ ル デ ィ ス ク リ プ タ ー を select(2), poll(2), epoll(7) で 監 視 で き る と い う 利 点 が あ る 。 こ れ ら の シ ス テ ム コ ー ル を 使 う の は 、 そ れ ぞ れ timer_create(2), timer_settime(2), timer_gettime(2) を 使 う の と 同 様 で あ る (timer_getoverrun(2) に 対 応 す る も の は な く 、 以 下 で 説 明 す る よ う に こ の 機 能 は read(2) に よ り 提 供 さ れ る )。
timerfd_create()
timerfd_create() は 新 規 の
タ イ マ ー オ ブ
ジ ェ ク ト を 生
成 し 、 そ の タ
イ マ ー を 参 照
す る フ ァ イ ル
デ ィ ス ク リ プ
タ ー を 返 す 。
clockid 引 き 数 は 、
タ イ マ ー の 進
捗 を 管 理 す る
た め の ク ロ ッ
ク を 指 定 す る
も の で 、 CLOCK_REALTIME
か CLOCK_MONOTONIC の い ず
れ か で な け れ
ば な ら な い 。
CLOCK_REALTIME は シ ス テ
ム 全 体 で 使 用
さ れ る ク ロ ッ
ク で 、 こ の ク
ロ ッ ク は 変 更
可 能 で あ る 。
CLOCK_MONOTONIC は 変 更 さ
れ る こ と の な
い ク ロ ッ ク で
、 (シ ス テ ム 時
刻 の 手 動 で の
変 更 な ど の ) シ
ス テ ム ク ロ ッ
ク の 不 連 続 な
変 化 の 影 響 を
受 け な い 。 こ
れ ら の ク ロ ッ
ク の 現 在 の 値
は clock_gettime(2) を 使 っ
て 取 得 で き る
。
Linux 2.6.27 以 降 で は 、 以 下 の 値 の い く つ か を ビ ッ ト 単 位 の 論 理 和 (OR) で 指 定 す る こ と で 、 timerfd_create() の 振 舞 い を 変 更 す る こ と が で き る 。
TFD_NONBLOCK 新 し く 生 成 さ れ る オ ー プ ン フ ァ イ ル 記 述 |
(open file |
description) の O_NONBLOCK フ ァ イ ル ス テ ー タ ス フ ラ グ を セ ッ ト す る 。 こ の フ ラ グ を 使 う こ と で 、 O_NONBLOCK を セ ッ ト す る た め に fcntl(2) を 追 加 で 呼 び 出 す 必 要 が な く な る 。
TFD_CLOEXEC 新 し い フ ァ イ ル デ ィ ス ク リ プ タ ー に 対 し て |
close−on−exec |
(FD_CLOEXEC) フ ラ グ を セ ッ ト す る 。 こ の フ ラ グ が 役 に 立 つ 理 由 に つ い て は 、 open(2) の O_CLOEXEC フ ラ グ の 説 明 を 参 照 の こ と 。 バ ー ジ ョ ン 2.6.26 以 前 の Linux で は 、 flags 引 き 数 は 未 使 用 で あ り 、 0 を 指 定 し な け れ ば な ら な い 。
timerfd_settime()
timerfd_settime() は 、 フ ァ
イ ル デ ィ ス ク
リ プ タ ー fd に
よ り 参 照 さ れ
る タ イ マ ー を
開 始 し た り 停
止 し た り す る
。
new_value 引 き 数 は 、 タ イ マ ー の 満 了 時 間 (expiration) の 初 期 値 と 間 隔 (interval) を 指 定 す る 。 こ の 引 き 数 で 使 用 さ れ て い る itimerspec 構 造 体 に は 2 つ の フ ィ ー ル ド が あ り 、 各 フ ィ ー ル ド は timespec 型 の 構 造 体 で あ る 。
struct timespec
{
time_t tv_sec; /* Seconds */
long tv_nsec; /* Nanoseconds */ };
struct
itimerspec {
struct timespec it_interval; /* Interval for periodic timer
*/
struct timespec it_value; /* Initial expiration */ };
new_value.it_value は タ イ マ ー の 満 了 時 間 の 初 期 値 を 、 秒 と ナ ノ 秒 で 指 定 す る 。 new_value.it_value の フ ィ ー ル ド の う ち 少 な く と も 一 方 に 0 以 外 の 値 を 設 定 す る と 、 タ イ マ ー が 開 始 さ れ る 。 両 方 の フ ィ ー ル ド に 0 を 設 定 す る と 、 タ イ マ ー が 停 止 す る 。
new_value.it_interval は タ イ マ ー の 一 回 目 の 満 了 後 に 繰 り 返 し タ イ マ ー の 満 了 間 隔 を 、 秒 と ナ ノ 秒 で 指 定 す る 。 new_value.it_interval の フ ィ ー ル ド の う ち 少 な く と も 一 方 に 0 以 外 の 値 を 設 定 す る と 、 繰 り 返 し タ イ マ ー が 有 効 に な る 。 両 方 の フ ィ ー ル ド に 0 を 設 定 し た 場 合 、 タ イ マ ー は new_value.it_value で 指 定 さ れ た 時 間 後 に 、 一 回 だ け 満 了 し て 停 止 す る 。
flags 引 き 数 に は 0 か TFD_TIMER_ABSTIME を 指 定 す る 。 0 は 相 対 時 刻 タ イ マ ー を 意 味 し 、 new_value.it_value で は clockid で 指 定 さ れ た ク ロ ッ ク の 現 在 の 値 か ら の 相 対 的 な 時 刻 を 指 定 す る 。 TFD_TIMER_ABSTIME は 絶 対 時 刻 タ イ マ ー を 意 味 し 、 new_value.it_interval で は clockid で 指 定 さ れ た ク ロ ッ ク の 絶 対 時 刻 を 指 定 す る 。 つ ま り 、 ク ロ ッ ク の 値 が new_value.it_interval で 指 定 さ れ た 時 刻 に 達 し た ら 、 タ イ マ ー が 満 了 す る 。
old_value 引 き 数 が NULL で な い 場 合 、 old_value 引 き 数 が 指 す itimerspec 構 造 体 は 、 timerfd_settime() を 呼 び 出 し た 時 点 で の タ イ マ ー の 設 定 を 返 す の に 使 用 さ れ る 。 下 記 の timerfd_gettime() の 説 明 を 参 照 。
timerfd_gettime()
timerfd_gettime() は 、 フ ァ
イ ル デ ィ ス ク
リ プ タ ー fd で
参 照 さ れ る タ
イ マ ー の 現 在
の 設 定 が 入 っ
た itimerspec 構 造 体
を 、 curr_value に 格
納 し て 返 す 。
it_value フ ィ ー ル ド は 、 タ イ マ ー が 次 に 満 了 す る ま で の 残 り 時 間 を 返 す 。 こ の 構 造 体 の 両 方 の フ ィ ー ル ド が 0 で あ れ ば 、 タ イ マ ー は 現 在 停 止 し て い る 。 タ イ マ ー 設 定 時 に TFD_TIMER_ABSTIME フ ラ グ が 指 定 さ れ た か に 関 わ ら ず 、 こ の フ ィ ー ル ド は 常 に 相 対 値 が 格 納 さ れ る 。
it_interval
フ ィ ー ル ド は
、 タ イ マ ー の
間 隔 を 返 す 。
こ の 構 造 体 の
両 方 の フ ィ ー
ル ド が 0 で あ れ
ば 、 タ イ マ ー
は new_value.it_value で 指
定 さ れ た 時 間
後 に 一 回 だ け
満 了 し て 停 止
す る よ う に 設
定 さ れ て い る
。 タ イ マ ー フ
ァ イ ル デ ィ ス
ク リ プ タ ー に
対 す る 操 作
timerfd_create() が 返 す フ
ァ イ ル デ ィ ス
ク リ プ タ ー は
以 下 の 操 作 を
サ ポ ー ト し て
い る 。
read(2)
timerfd_settime() を 使 っ て タ イ マ ー の 設 定 が 最 後 変 更 さ れ て 以 降 、 ま た は read(2) の 呼 び 出 し に 最 後 に 成 功 し て 以 降 に 、 タ イ マ ー の 満 了 が 一 回 以 上 発 生 し て い れ ば 、 read(2) に 渡 さ れ た バ ッ フ ァ ー に 、 タ イ マ ー 満 了 回 数 を 示 す 8 バ イ ト の unsigned 型 の 整 数 (uint64_t) が 返 さ れ る (返 さ れ る 値 は ホ ス ト バ イ ト オ ー ダ 、 つ ま り そ の ホ ス ト マ シ ン に お け る 整 数 の 通 常 の バ イ ト オ ー ダ で あ る )。
read(2) を 行 っ た 時 点 で タ イ マ ー の 満 了 が 発 生 し て い な け れ ば 、 read(2) は 停 止 (block) す る 、 も し く は フ ァ イ ル デ ィ ス ク リ プ タ ー が 非 停 止 (nonblocking) に 設 定 さ れ て い る 場 合 は エ ラ ー EAGAIN で 失 敗 す る (非 停 止 モ ー ド に す る に は 、 fcntl(2) の F_SETFL 命 令 で O_NONBLOCK フ ラ グ を セ ッ ト す る )。 渡 さ れ た バ ッ フ ァ ー の 大 き さ が 8 バ イ ト 未 満 の 場 合 、 read(2) は エ ラ ー EINVAL で 失 敗 す る 。
poll(2),
select(2) (と 同 様 の
操 作 ) 一 つ 以 上
の タ イ マ ー 満
了 が 発 生 し て
い れ ば 、 フ ァ
イ ル デ ィ ス ク
リ プ タ ー は 読
み 出 し 可 能 と
な る (select(2) の readfds
引 き 数 や poll(2) の
POLLIN フ ラ グ )。 こ
の フ ァ イ ル デ
ィ ス ク リ プ タ
ー は 、 他 の フ
ァ イ ル デ ィ ス
ク リ プ タ ー 多
重 API で あ る pselect(2),
ppoll(2), epoll(7) も サ ポ
ー ト し て い る
。
close(2) フ ァ イ ル デ
ィ ス ク リ プ タ
ー が そ れ 以 降
は 必 要 な く な
っ た 際 に は 、
ク ロ ー ズ す べ
き で あ る 。 同
じ timer オ ブ ジ ェ ク
ト に 関 連 付 け
ら れ た フ ァ イ
ル デ ィ ス ク リ
プ タ ー が 全 て
ク ロ ー ズ さ れ
る と 、 そ の タ
イ マ ー は 解 除
さ れ 、 そ の オ
ブ ジ ェ ク ト 用
の 資 源 が カ ー
ネ ル に よ り 解
放 さ れ る 。
fork(2)
で の 扱 い
fork(2) が 行 わ れ る
と 、 子 プ ロ セ
ス は timerfd_create() に よ
り 生 成 さ れ た
フ ァ イ ル デ ィ
ス ク リ プ タ ー
の コ ピ ー を 継
承 す る 。 そ の
フ ァ イ ル デ ィ
ス ク リ プ タ ー
は 、 親 プ ロ セ
ス の 対 応 す る
フ ァ イ ル デ ィ
ス ク リ プ タ ー
と 同 じ タ イ マ
ー オ ブ ジ ェ ク
ト を 参 照 し て
お り 、 子 プ ロ
セ ス の read(2) で も
同 じ タ イ マ ー
の 満 了 に 関 す
る 情 報 が 返 さ
れ る 。
execve(2)
で の 扱 い
execve(2) の 前 後 で
timerfd_create() に よ り 生
成 さ れ た フ ァ
イ ル デ ィ ス ク
リ プ タ ー は 保
持 さ れ 、 タ イ
マ ー が 開 始 さ
れ て い た 場 合
に は タ イ マ ー
の 満 了 が 発 生
し 続 け る 。
返 り 値
成 功 す る と 、 timerfd_create() は 新 し い フ ァ イ ル デ ィ ス ク リ プ タ ー を 返 す 。 エ ラ ー の 場 合 、 −1 を 返 し 、 errno に エ ラ ー を 示 す 値 を 設 定 す る 。
timerfd_settime() と timerfd_gettime() は 成 功 す る と 0 を 返 す 。 エ ラ ー の 場 合 、 −1 を 返 し 、 errno に エ ラ ー を 示 す 値 を 設 定 す る 。
エ ラ ー
timerfd_create() は 以 下 の エ ラ ー で 失 敗 す る 可 能 性 が あ る 。
EINVAL |
clockid 引 き 数 が CLOCK_MONOTONIC で も CLOCK_REALTIME で も な い 。 | ||
EINVAL |
flags が 無 効 で あ る 。 も し く は 、 Linux 2.6.26 以 前 の 場 合 に は flags が 0 以 外 で あ る 。 | ||
EMFILE |
オ ー プ ン 済 み の フ ァ イ ル デ ィ ス ク リ プ タ ー の 数 が プ ロ セ ス あ た り の 上 限 に 達 し て い た 。
ENFILE オ ー プ ン 済 み の フ ァ イ ル 総 数 が シ ス テ ム 全 体 の 上 限 に 達 し て い た 。 | |
ENODEV |
(カ ー ネ ル 内 の ) 無 名 inode デ バ イ ス を マ ウ ン ト で き な か っ た 。
ENOMEM タ イ マ ー を 作 成 す る の に 十 分 な カ ー ネ ル メ モ リ ー が な か っ た 。 |
timerfd_settime() と timerfd_gettime() は 以 下 の エ ラ ー で 失 敗 す る 可 能 性 が あ る 。
EBADF |
fd が 有 効 な フ ァ イ ル デ ィ ス ク リ プ タ ー で な い 。 | ||
EFAULT |
new_value, old_value, curr_value が 有 効 な ポ イ ン タ ー で は な い 。 | ||
EINVAL |
fd が 有 効 な timerfd フ ァ イ ル デ ィ ス ク リ プ タ ー で な い 。 |
timerfd_settime() は 以 下 の エ ラ ー で 失 敗 す る こ と も あ る 。
EINVAL |
new_value が 適 切 に 初 期 化 さ れ て い な い (tv_nsec の 一 つ が 0 か ら 999,999,999 ま で の 範 囲 に 入 っ て い な い )。 | ||
EINVAL |
flags が 無 効 で あ る 。 |
バ ー ジ ョ ン
こ れ ら の シ ス テ ム コ ー ル は カ ー ネ ル 2.6.25 以 降 の Linux で 利 用 可 能 で あ る 。 ラ イ ブ ラ リ 側 の サ ポ ー ト は バ ー ジ ョ ン 2.8 以 降 の glibc で 提 供 さ れ て い る 。
準 拠
こ れ ら の シ ス テ ム コ ー ル は Linux 固 有 で あ る 。
バ グ
現 在 の と こ ろ 、 timerfd_create() が 対 応 し て い る clockid の 種 類 は timer_create(2) よ り も 少 な い 。
例
以 下 の プ ロ グ ラ ム は 、 タ イ マ ー を 作 成 し 、 そ の 進 捗 を モ ニ タ ー す る も の で あ る 。 こ の プ ロ グ ラ ム は 最 大 で 3 個 の コ マ ン ド ラ イ ン 引 き 数 を 取 り 、 第 一 引 き 数 で は タ イ マ ー の 満 了 時 間 の 初 期 値 (秒 数 単 位 ) を 、 第 二 引 き 数 で は タ イ マ ー の 間 隔 (秒 数 単 位 ) を 、 第 三 引 き 数 で は タ イ マ ー が 何 回 満 了 し た ら プ ロ グ ラ ム が 終 了 す る か を 指 定 す る 。 第 二 引 き 数 と 第 三 引 き 数 は 省 略 可 能 で あ る 。 以 下 の シ ェ ル の セ ッ シ ョ ン は こ の プ ロ グ ラ ム の 使 用 例 を 示 し た も の で あ る 。
$ a.out 3 1
100
0.000: timer started
3.000: read: 1; total=1
4.000: read: 1; total=2
^Z # type control−Z to suspend the program
[1]+ Stopped ./timerfd3_demo 3 1 100
$ fg # Resume execution after a few seconds
a.out 3 1 100
9.660: read: 5; total=7
10.000: read: 1; total=8
11.000: read: 1; total=9
^C # type control−C to suspend the program
プ ロ グ ラ ム の
ソ ー ス
#include <sys/timerfd.h>
#include <time.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)
static void
print_elapsed_time(void)
{
static struct timespec start;
struct timespec curr;
static int first_call = 1;
int secs, nsecs;
if (first_call)
{
first_call = 0;
if (clock_gettime(CLOCK_MONOTONIC, &start) == −1)
handle_error("clock_gettime"); }
if
(clock_gettime(CLOCK_MONOTONIC, &curr) == −1)
handle_error("clock_gettime");
secs =
curr.tv_sec − start.tv_sec;
nsecs = curr.tv_nsec − start.tv_nsec;
if (nsecs < 0) {
secs−−;
nsecs += 1000000000; }
printf("%d.%03d: ", secs, (nsecs + 500000) /
1000000); }
int
main(int argc, char *argv[])
{
struct itimerspec new_value;
int max_exp, fd;
struct timespec now;
uint64_t exp, tot_exp;
ssize_t s;
if ((argc != 2)
&& (argc != 4)) {
fprintf(stderr, "%s init−secs
[interval−secs max−exp]\n",
argv[0]);
exit(EXIT_FAILURE); }
if
(clock_gettime(CLOCK_REALTIME, &now) == −1)
handle_error("clock_gettime");
/* Create a
CLOCK_REALTIME absolute timer with initial
expiration and interval as specified in command line */
new_value.it_value.tv_sec
= now.tv_sec + atoi(argv[1]);
new_value.it_value.tv_nsec = now.tv_nsec;
if (argc == 2) {
new_value.it_interval.tv_sec = 0;
max_exp = 1; }
else {
new_value.it_interval.tv_sec = atoi(argv[2]);
max_exp = atoi(argv[3]); }
new_value.it_interval.tv_nsec = 0;
fd =
timerfd_create(CLOCK_REALTIME, 0);
if (fd == −1)
handle_error("timerfd_create");
if
(timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value,
NULL) == −1)
handle_error("timerfd_settime");
print_elapsed_time();
printf("timer started\n");
for (tot_exp =
0; tot_exp < max_exp;) {
s = read(fd, &exp, sizeof(uint64_t));
if (s != sizeof(uint64_t))
handle_error("read");
tot_exp += exp;
print_elapsed_time();
printf("read: %llu; total=%llu\n",
(unsigned long long) exp,
(unsigned long long) tot_exp); }
exit(EXIT_SUCCESS); }
関 連 項 目
eventfd(2), poll(2), read(2), select(2), setitimer(2), signalfd(2), timer_create(2), timer_gettime(2), timer_settime(2), epoll(7), time(7)
こ の 文 書 に つ い て
こ の man ペ ー ジ は Linux man−pages プ ロ ジ ェ ク ト の リ リ ー ス 3.79 の 一 部 で あ る 。 プ ロ ジ ェ ク ト の 説 明 と バ グ 報 告 に 関 す る 情 報 は http://www.kernel.org/doc/man−pages/ に 書 か れ て い る 。