mokky14's IT diary

IT関係の仕事メモ、勉強会の感想など書いてます。

C言語での定周期処理の実装(setitimer)

シグナルについて調べてたら、定周期でイベント通知するAPI見つけたのでメモ。
今までC言語で定周期処理を実装するのに、処理終わった後でsleepするようなプログラム組んでたけど、こっちの方が楽そう。

以下、試したサンプル。
シグナルハンドラは嫌いなので、シグナルをブロックして、sigwaitでシグナルを待ち受けるようにしてる。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <signal.h>
#include <pthread.h>
#include <errno.h>

int main() {
        // setitimerにより通知されるシグナルをマスク
        sigset_t sigset;
        sigemptyset(&sigset);
        sigaddset(&sigset, SIGALRM);
        pthread_sigmask(SIG_BLOCK, &sigset, NULL);

        // タイマ設定 5秒毎に通知
        const struct timeval interval = { 5, 0 };
        const struct itimerval itimer = {interval, interval};
        int ret = setitimer(ITIMER_REAL, &itimer, NULL);
        if ( ret != 0 ) {
                perror("setitimer error");
                return -1;
        }

        int i;
        for ( i=0; i<10; i++ ) {
                int signo;
                sigwait(&sigset, &signo);

                struct timeval tv;
                gettimeofday(&tv, NULL);
                char    timebuf[26];
                ctime_r(&tv.tv_sec, timebuf);
                *strchr(timebuf, '\n') = '\0';
                printf("[%s] [%06d] signal[%d] recieved.\n",
                        timebuf, tv.tv_usec, signo);

                // たまに時間かかる処理がある想定
                if ( i % 4 == 3 ) {
                        unsigned int waittime = 7;
                        printf("wait %d seconds.\n", waittime);
                        sleep(waittime);
                }
        }

        return 0;
}

実行結果

[~]$ cc timer.c -lpthread
[~]$ ./a.out
[Wed Apr  3 16:15:59 2013] [896773] signal[14] recieved.
[Wed Apr  3 16:16:04 2013] [896998] signal[14] recieved.
[Wed Apr  3 16:16:09 2013] [896241] signal[14] recieved.
[Wed Apr  3 16:16:14 2013] [896484] signal[14] recieved.
wait 7 seconds.
[Wed Apr  3 16:16:21 2013] [896823] signal[14] recieved.
[Wed Apr  3 16:16:24 2013] [896970] signal[14] recieved.
[Wed Apr  3 16:16:29 2013] [897215] signal[14] recieved.
[Wed Apr  3 16:16:34 2013] [896484] signal[14] recieved.
wait 7 seconds.
[Wed Apr  3 16:16:41 2013] [896852] signal[14] recieved.
[Wed Apr  3 16:16:44 2013] [896946] signal[14] recieved.

(追記)
いいもの見つけたと思ったら、setitimerは廃止予定らしい。*1
代わりにtimer_settime(2)を使えと。

後で調べてみよう。