/var/log/messages

Sep 25, 2014 - 2 minute read - Comments - Linux

何秒か後にこれやっといて、な実装について (Linux における C での実装)

ちょっと順に色々確認してみた記録を自分メモ。手順としては

  • signal handler を設定
  • interval time を設定
  • timer_settime を呼び出してタイマを設定

というカンジ。まず、以下からパクッた実装を確認しつつ man sigaction を確認してみます。

まず、signal handler を設定、というあたりから。実装は以下なカンジです。

struct sigaction action;

/* set signal handler */
action.sa_sigaction = SigHandler;
action.sa_flags = SA_SIGINFO | SA_RESTART;
sigemptyset(&action.sa_mask);
if (sigaction(SIGRTMIN + 1, &action, NULL) < 0) {
    perror("sigaction error");
    exit(1);
}

SigHandler な手続き定義は以下です。

void SigHandler(int signum, siginfo_t *info, void *ctxt) {

man を確認してみるに以下な記述がありました。

If SA_SIGINFO is specified in sa_flags, then sa_sigaction (instead of sa_handler) specifies the signal-handling function for signum.

なので SigHandler な定義は sa_sigaction と同じ型にしているのか。あと、sa_flags 属性に設定している flag について確認してみます。

まず、SA_RESTART からですが、以下な記述です。

Provide behavior compatible with BSD signal semantics by making certain system calls restartable across signals.

これ、signal (7) の man によれば _システムコールやライブラリが停止 (block) している間にシグナルハンドラが起動_ された時の挙動を指定しているのか。

また、SA_SIGINFO は上で確認した通りで

The signal handler takes three arguments, not one.

とのこと。また、sigemptyset は

initializes the signal set given by set to empty, with all signals excluded from the set.

という説明があります。struct sigaction な領域についてこれらの初期化を行なった後に sigaction という手続きを呼び出しています。man によれば

The sigaction() system call is used to change the action taken by a process on receipt of a specific signal.

ここではリアルタイムシグナル、というものを使っていますね。とりあえず使ってみました、という話になっている事を願う。

interval timer の設定

実装の例が以下。

struct sigevent event;
struct timer_t timerid = 0;

event.sigev_notify = SIGEV_SIGNAL;
event.sigev_signo = SIGRTMIN + 1;
if (timer_create(CLOCK_READTIME, &event, &timerid)) {
    perror("timer_create error");
}

timer_create 手続きを使って POSIX per-process timer を作ります。第一引数には CLOCK_REALTIME を渡しています。man の説明が以下。

A settable system-wide real-time clock

また第二引数に struct sigevent 型の領域の先頭アドレスを渡しています。see sigevent(7) とあるのでこちらも確認してみます。

struct sigevent な sigev_notify 属性には SIGEV_SIGNAL が設定されてます。man によれば以下とのこと。

Notify the process by sending the signal specified in sigev_signo

シグナル番号は sigev_signo に設定されてます。リアルタイムシグナルな SIGRTMIN + 1 が設定されています。また、第三引数な struct timer なソレは適切な何か、が設定されるに違いない、という事にしておきます。

最後に

タイマの設定ですが以下が実装例です。ここでは 4 秒後のタイマを作っています。signal handler は一度だけしか呼び出されない形です。

struct itimerspec spec;

spec.it_interval.tv_sec = 0;
spec.it_interval.tv_nsec = 0;
spec.it_value.tv_sec = 4;
spec.it_value.tv_nsec = 0;

if (timer_settime(timerid, 0, &spec, NULL) < 0) {
    perror("timer_settime error");
}

timerid は先に呼び出した timer_create に渡したものを使います。これで 4 秒後に SIGRTMIN + 1 な signal が発生して handler が呼び出されます。