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

Takenoshita Koyo email@hidden
2011年 1月 27日 (木) 16:24:05 JST


竹之下です。

> タイマーシグナル(割り込み)がselect実行中に発生した場合、
> selectはエラーで返ってerrnoがEINTRになるはずです。
timer_createのmanページには、以下のように書いてありますね。

http://www.kernel.org/doc/man-pages/online/pages/man2/timer_create.2.html
> int timer_create(clockid_t clockid, struct sigevent *sevp,
>                  timer_t *timerid);
...
> Specifying sevp as NULL is equivalent to specifying a pointer to a sigevent
> structure in which sigev_notify is SIGEV_SIGNAL, sigev_signo is SIGALRM, and
> sigev_value.sival_int is the timer ID.

sevpをNULLにすると、SIGALMが発生するようです。

> 正しい挙動です。
シグナルを使い出すと、途端に普段意図していない動きをしだすので、
とにかく全てのシステムコールの戻り値を、くどいぐらいに確認したほうが良いです。
read()やwrite()も失敗することがあります。
perror()やstrerr()などでerrnoを確認することができます。

その他のチェックポイントとしては、
- CLOCK_REALTIMEではなくCLOCK_MONOTONICを使う
  CLOCK_REALTIMEはシステムクロックの影響を受けます。

- シグナルハンドラ内でprintf()してはいけない
  サンプルコードなので、簡単な例ということなのかもしれませんが、
  シグナルハンドラ内では「非同期シグナルセーフ」な関数しか使ってはいけません。
  参照: UNIX上でのC++ソフトウェア設計の定石 (2)/memologue
        http://d.hatena.ne.jp/yupo5656/20040712/p2

などがあります。

socketへのread/writeとタイマー(ないし、それに伴うシグナル)を上手く扱うのは
とても難しい問題です。一つの解として、タイマーもシグナルも
ファイルディスクリプタとして扱ってしまい、全部select()で監視する
という手があります。

そのために、timerfd、signalfd、eventfdなどの仕組みがあります。
参照: ファイルディスクリプタについて/CodeZine
      http://codezine.jp/article/corner/356

が、これらの仕組みは比較的新しいので、環境によっては使えないこともあります。

比較的移植性の高い方法としては、pipe()を使う方法でしょうか。
参照: ファイルディスクリプタについて/pipe(2)との併用/CodeZine
      http://codezine.jp/article/detail/4799?p=3

以上、ご参考になれば。

-- 
Koyo Takenoshita




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