ループ内で を呼び出すだけpause()
です。これはブロックされ、シグナルが受信されたときにのみ返されるため、コードを実行し、再度ループして、繰り返すことができます。プログラムの終了を停止するには、シグナル ハンドラーが必要ですが、SIGALRM
何もする必要はありません。関数本体を空のままにしておくことができます。
例えば:
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
void timer_handler(int signum)
{
(void) signum; /* Avoids warning for unused argument */
}
int main(void)
{
struct sigaction sa;
sa.sa_handler = timer_handler;
sa.sa_mask = 0;
sa.sa_flags = 0;
sigaction(SIGALRM, &sa, NULL);
struct itimerval timer;
timer.it_value.tv_sec = 1;
timer.it_value.tv_usec = 0;
timer.it_interval.tv_sec = 1;
timer.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL, &timer, NULL);
while ( 1 ) {
pause();
printf("Timer expired - get GPS data.\n");
}
return 0;
}
出力が得られます:
paul@horus:~/src/sandbox$ ./alarm
Timer expired - get GPS data.
Timer expired - get GPS data.
Timer expired - get GPS data.
Timer expired - get GPS data.
Timer expired - get GPS data.
Timer expired - get GPS data.
Timer expired - get GPS data.
Timer expired - get GPS data.
^C
paul@horus:~/src/sandbox$
それはかなり大雑把な解決策です。コードの実行にタイマー間隔よりも時間がかかる可能性がある場合は、信頼性が低くなり、シグナルをスキップすることがあります。あなたはこれを気にするかもしれませんし、気にしないかもしれません。より洗練されたアプローチとして、シグナルの受信をブロックし、ブロックを解除するシグナル マスクを使用してSIGALRM
呼び出すことができますsigsuspend()
。シグナルのブロック解除と待機はアトミック操作であることがわかっているため安全です。そのアプローチの例を次に示します。
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
void timer_handler(int signum)
{
static const char msg[] = "Handler was called.\n";
write(STDIN_FILENO, msg, sizeof(msg) - 1);
(void) signum;
}
int main(void)
{
struct sigaction sa;
sa.sa_handler = timer_handler;
sa.sa_mask = 0;
sa.sa_flags = 0;
sigaction(SIGALRM, &sa, NULL);
struct itimerval timer;
timer.it_value.tv_sec = 1;
timer.it_value.tv_usec = 0;
timer.it_interval.tv_sec = 1;
timer.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL, &timer, NULL);
sigset_t old_mask, block_mask;
sigemptyset(&block_mask);
sigaddset(&block_mask, SIGALRM);
sigprocmask(SIG_BLOCK, &block_mask, &old_mask);
sleep(3); /* To demonstrate signal handler won't be
called until sigsuspend() is called, timer
is firing every second while we're sleeping */
while ( 1 ) {
sigsuspend(&old_mask);
printf("Timer expired - get GPS data.\n");
}
return 0;
}
出力付き:
paul@horus:~/src/sandbox$ ./alarm2
Handler was called.
Timer expired - get GPS data.
Handler was called.
Timer expired - get GPS data.
Handler was called.
Timer expired - get GPS data.
Handler was called.
Timer expired - get GPS data.
Handler was called.
Timer expired - get GPS data.
Handler was called.
Timer expired - get GPS data.
^C
paul@horus:~/src/sandbox$
上記の例では簡潔にするためにエラー チェックは省略されていますが、もちろん、コードにはすべてのシステム コールにエラー チェックが含まれている必要があります。