実時間アプリケーションは、インタバルタイマを使用して活動をスケジュールすることがよくあります。インタバルタイマには、「単発」型と「周期」型の 2 種類があります。
単発タイマは、現在時間または絶対時間に相対的な有効時間に設定されるタイマです。タイマは、有効時間が終了すると解除されます。このようなタイマは、データを記憶領域に転送した後のバッファの消去や操作のタイムアウトの管理に便利です。
周期タイマには、初期有効時間 (絶対時間または相対時間) と繰り返しインタバルが設定されています。インタバルタイマの有効時間が経過するたびに、タイマは繰り返し再ロードされ、自動的に再度有効になります。このタイマはデータロギングやサーボ制御に便利です。インタバルタイマ機能を呼び出す際は、システムのハードウェア定期タイマの解像度より小さな時間値は、ハードウェア定期タイマインタバル (10 ミリ秒) の時間値より大きい最小の倍数に丸められます。
SunOS 5.0 から 5.8 には、setitimer(2) インタフェースと getitimer(2) インタフェースの 2 組のタイマインタフェースがあります。これらのインタフェースは、タイムインタバルを指定する timeval 構造体を使用して、BSD タイマと呼ばれる固定設定タイマを動作させます。POSIX タイマである timer_create(3RT)、CLOCK_REALTIME は、POSIX クロック CLOCK_REALTIME を動作させます。POSIX タイマの動作は、timespec 構造体によって表されます。
getitimer(2) 関数と setitimer(2) 関数は、それぞれ指定された BSD インタバルタイマの値の取り出しと設定を行います。プロセスは ITIMER_REAL で指定する実時間タイマを含め、3 つの BSD インタバルタイマを利用できます。BSD タイマを使用して有効になっている場合は、システムによってタイマにふさわしいシグナルがタイマを設定したプロセスに送信されます。
timer_create(3RT) は、{TIMER_MAX} 個までの POSIX タイマを生成できます。呼び出し側はタイマの有効時間が経過したときに、どのシグナルと関連値をプロセスに送るかを指定できます。timer_settime(3RT) と timer_gettime(3RT) は、指定された POSIX インタバルタイマの値を、それぞれ設定および検索します。必要なシグナルが保留状態にある間に POSIX タイマの有効時間が経過すると配信がカウントされ、timer_getoverrun(3RT) はそのような有効時間切れのカウントを検索します。timer_delete(3RT) は、POSIX タイマの割り当てを解除します。
例 8-1 に、setitimer(2) を使用して定期割り込みを発生させる方法とタイマ割り込みの到着の制御方法を示します。
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
#define TIMERCNT 8
void timerhandler();
int timercnt;
struct timeval alarmtimes[TIMERCNT];
main()
{
struct itimerval times;
sigset_t sigset;
int i, ret;
struct sigaction act;
siginfo_t si;
/* SIGALRM をブロッキングする */
sigemptyset (&sigset);
sigaddset (&sigset, SIGALRM);
sigprocmask (SIG_BLOCK, &sigset, NULL);
/* SIGALRM のためのハンドラを設定する */
act.sa_action = timerhandler;
sigemptyset (&act.sa_mask);
act.sa_flags = SA_SIGINFO;
sigaction (SIGALRM, &act, NULL);
/*
* 3 秒後に開始し、そのあとは 3 分の 1 秒おきに開始するように
* インタバルタイマを設定する
*/
times.it_value.tv_sec = 3;
times.it_value.tv_usec = 0;
times.it_interval.tv_sec = 0;
times.it_interval.tv_usec = 333333;
ret = setitimer (ITIMER_REAL, ×, NULL);
printf ("main:setitimer ret = %d¥n", ret);
/* 現在はアラーム待ち */
sigemptyset (&sigset);
timerhandler (0, si, NULL);
while (timercnt < TIMERCNT) {
ret = sigsuspend (&sigset);
}
printtimes();
}
void timerhandler (sig, siginfo, context)
int sig;
siginfo_t *siginfo;
void *context;
{
printf ("timerhandler:start¥n");
gettimeofday (&alarmtimes[timercnt], NULL);
timercnt++;
printf ("timerhandler:timercnt = %d¥n", timercnt);
}
printtimes ()
{
int i;
for (i = 0; i < TIMERCNT; i++) {
printf("%ld.%0l6d¥n", alarmtimes[i].tv_sec,
alarmtimes[i].tv_usec);
}
}
|