Manpages

名 前

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_REALTIMECLOCK_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/ に 書 か れ て い る 。