POSIX周期タイマー
(プログラムの概要)
インターバルタイマーのPOSIXタイマー版です。前述のSIGALRMを使用したインターバルタイマーと同じく10ms毎に設定したシグナル(今回はリアルタイムシグナルであるSIG35)を通知し周期を刻みます。

サンプルソース
/* * sample program * POSIX interval timer */ #include <stdio.h> #include <stdlib.h> #include <sys/time.h> #include <signal.h> #include <string.h> #include <time.h> #include <unistd.h> #include <errno.h> void SignalHandler(int, siginfo_t*, void*); int _nanosleep(int, int); int main(void) { struct sigaction action; struct sigevent evp; struct itimerspec ispec; timer_t timerid = 0; printf("sample program(%s) start\n", __FILE__); memset(&action, 0, sizeof(action)); memset(&evp, 0, sizeof(evp)); /* set signal handler */ action.sa_sigaction = SignalHandler; action.sa_flags = SA_SIGINFO | SA_RESTART; sigemptyset(&action.sa_mask); if(sigaction(SIGRTMIN + 1, &action, NULL) < 0){ perror("sigaction error"); exit(1); } /* set intarval timer (10ms) */ evp.sigev_notify = SIGEV_SIGNAL; evp.sigev_signo = SIGRTMIN + 1; if(timer_create(CLOCK_REALTIME, &evp, &timerid) < 0){ perror("timer_create error"); exit(1); } ispec.it_interval.tv_sec = 0; ispec.it_interval.tv_nsec = 10000000; ispec.it_value.tv_sec = 0; ispec.it_value.tv_nsec = 10000000; if(timer_settime(timerid, 0, &ispec, NULL) < 0){ perror("timer_settime error"); exit(1); } /* loop */ while(1){ _nanosleep(1, 0); /* sleep 1 sec */ } return 0; } void SignalHandler(int signum, siginfo_t *info, void *ctxt) { static unsigned long msec_cnt = 0; msec_cnt++; if(!(msec_cnt % 100)){ printf("SignalHandler:%lu sec\n", (msec_cnt / 100)); } return; } int _nanosleep(int sec, int nsec) { struct timespec req, rem; req.tv_sec = sec; req.tv_nsec = nsec; rem.tv_sec = 0; rem.tv_nsec = 0; while(nanosleep(&req, &rem)){ if(errno == EINTR){ req.tv_sec = rem.tv_sec; req.tv_nsec = rem.tv_nsec; }else{ perror("nanosleep error"); return -1; } } return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
(サブルーチンの説明)
SignalHandler():シグナルを通知された時に起動してもらうシグナルハンドラー関数。
_nanosleep():nanosleep()のラッパーです。
(プログラム解説)
各システムコールの詳細はmanコマンドで調べて下さい。

28行目~34行目:シグナルハンドラーの登録
今回はリアルタイムシグナルを使ってみます。リアルタイムシグナルを使用する場合はSIGRTMIN+XXという形で使用します。sa_flagsにSA_SIGINFOを指定した場合sa_handlerではなくsa_sigactionでシグナルハンドラーを設定します。この場合シグナルハンドラーの引数が変わります、詳細はsigactionのマニュアルを参照下さい。

37行目~50行目:インターバルタイマーの設定
timer_create()でタイマーを作成し、timer_settime()でタイマーで10msのインターバルタイマーを設定しています。timer_createはPOSIXインターバルタイマーを作成します。

evp.sigev_notify = SIGEV_SIGNAL; evp.sigev_signo = SIGRTMIN + 1;
37 38
37,38行目でタイムアウト時にシグナルを通知、シグナル番号はSIGRTMIN+1を設定しています。
43~46行目は初回起動までの時間とインターバル時間(ナノ秒)を指定します。

53行目からmain関数はスリープし続けます。(ctrl+cを押すと終了)


(コンパイルと動作)
gcc -Wall sigrt_timer.c -lrt
-lrtオプションをつけてコンパイルして下さい。
10ms毎にSignalHandler()が起動されカウントアップし、1秒に1回経過時間を出力します。