[Armadillo:06661] Re: Armadillo-300 にて、タイマーと select を使うには?

TATENO Hiroyuki email@hidden
2011年 1月 27日 (木) 17:48:03 JST


舘野です。

> そのために、timerfd、signalfd、eventfdなどの仕組みがあります。

linux kernel 2.6.26(A4x0やA500)ならば、timerfdやsignalfdが使用可能です。
ただ、libcにエントリーが無いので、自前でsyscallしてやる必要はあります。
A440で使用した時には、以下のような関数を自作しました。

#include <sys/syscall.h>

int signalfd(int fd, sigset_t* pmask) {
    return syscall(SYS_signalfd, fd, pmask);
}

int timerfd_create(int clockid, int flags) {
    return syscall(SYS_timerfd_create, clockid, flags);
}
int timerfd_settime(int fd, int flags, 
  const struct itimerspec* new_value, 
  struct itimerspec* old_value) {
    return syscall(SYS_timerfd_settime, fd, flags, new_value, old_value);
}
int timerfd_gettime(int fd, struct itimerspec* curr_value) {
    return syscall(SYS_timerfd_gettime, fd, curr_value);
}


> 比較的移植性の高い方法としては、pipe()を使う方法でしょうか。
>       http://codezine.jp/article/detail/4799?p=3

signalfdが使えない場合、上記方法が安全で無難だと思います。


タイマー周期での処理が、厳密である必要が無く「おおよそ」の時間で
処理しても良いのならば、selectのタイムアウトを利用するというのも
安全で安易な方法だと思います。

struct timeval tv;
int res;

tv.tv_sec = 1;
tv.tv_usec = 0;

res = select(FD_SETSIZE, &readfds, NULL, NULL, &tv);
if (res < 0) {
    /* タイムアウト. すなわち一定時間が経過した。 */

    /* 何かの定期処理を実行 */
} else if (res > 0) {
    /* socket等の処理 */
}


上記ですと、socket等のデバイス入力処理で時間が取られるので、
定期処理の時間に多少のバラつきが発生します。
socket処理とタイマー処理を別プロセスに分けて実行すれば、もう少し
精度は上がると思います。

#プロセス分けた場合、プロセス間通信という問題が発生しますけど、
#socketが扱えるのでしたら問題は無いと思います。


何にしても、signalは便利ではある反面、プログラムの難易度が高いので、
他の代替処理で可能かどうかを検討してみる価値はあるかと思います。


---
TETENO Hiroyuki




armadillo メーリングリストの案内