sevp.sigev_notify
を SIGEV_NONE
にし、なおかつ非常に先の時間を expiration に指定すれば、その時間までの残り時間を timer_gettime(2)
で取得できる。
あとは引き算をすればOK。「非常に先の時間」以上の時間を計測できないことになるが、 10億秒(31年)などを指定すれば用は足りそう。
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <time.h> #include <error.h> #include <sys/types.h> #include <sys/wait.h> // timer_settime(2) などの spec.it_value.tv_sec にセットできる最大値は // KTIME_SEC_MAX というカーネル定数で決まる模様で、 LONG_MAX より小さな値になる。 // see: https://elixir.bootlin.com/linux/v4.15/source/include/linux/time64.h#L40 #define TIMER_MAX 1000000000L int main(int argc, char *argv[]) { struct sigevent ev; struct itimerspec spec; ev.sigev_notify = SIGEV_NONE; timer_t t; if(timer_create(CLOCK_REALTIME, &ev, &t) < 0) { perror("timer_create"); exit(1); } spec.it_interval.tv_sec = 0; spec.it_interval.tv_nsec = 0; spec.it_value.tv_sec = TIMER_MAX; spec.it_value.tv_nsec = 0; if(timer_settime(t, 0, &spec, NULL) < 0) { perror("timer_create"); exit(1); } char *run[] = { "bash", "-i", NULL }; int status; pid_t pid = fork(); if(pid < 0) { perror("fork"); exit(1); } if(pid == 0) if(execv("/bin/bash", run) < 0) { perror("execv"); exit(1); } if(waitpid(pid, &status, 0) < 0) { perror("waitpid"); exit(1); } struct itimerspec retval; int ret = timer_gettime(t, &retval); if(ret < 0) { perror("timer_gettime"); exit(1); } else { long sec, nsec; if(!retval.it_value.tv_nsec) { sec = TIMER_MAX - retval.it_value.tv_sec; nsec = 0L; } else { sec = TIMER_MAX - retval.it_value.tv_sec - 1; nsec = 1000000000 - retval.it_value.tv_nsec; } printf("bash process ran in <%ld.%09ld> (s)\n", sec, nsec); } exit(0); }
$ gcc timer.c -o timer -lrt $ ./timer $ sleep 2 $ exit exit bash process ran in <3.432966856> (s)
今日も雑です。