[Armadillo:06924] Re: POSIXタイマー割り込みタイミング
email@hidden
2011年 3月 29日 (火) 10:54:33 JST
竹之下様
どうも有難うございます。
armadilloのタイマー周期が不定期になっていたのは別に起動していたスレッドが原因でした。
debian上ではタイマー起動部分とイベント処理のみを抜粋したため結果が異なってしまった様です。
別スレッドは常時TCPイベントを監視していたので、タイマーイベントが待たされていた様です。
スレッド処理内に1msecのsleepを入れたところ定周期でタイマーイベントが発生する様になりました。
お騒がせいました。
> -----Original Message-----
> From: Takenoshita Koyo
> Sent: Wed, Mar 23 2011 22:20:44 JST
> To: Armadillo series general discussion list
> Subject: [Armadillo:06915] Re: POSIXタイマー割り込みタイミング
>
> 竹之下です。
>
> タイマーの扱いと、シグナルの扱いは難しいですね。
> 色々な問題が絡み合っているので、インラインで書きます。
>
> email@hidden さんは書きました:
> > arnadillo-9にてPOSIXタイマーを100msec設定で動作させてみたところ、割り込み周期が不定な動きをしている様子だったので、ログで確認したところ、
> >
> > ->20msec
> > ->80msec
> > ->0msec
> > ->20msec
> > ->80msec
> > ->0msec
> >
> > と、3つを1つの周期として定期的に変なタイミングでタイマーイベントが発生していました。
> > 同じモジュールをPC上のdebianで動作させたところ、概ね100msecでイベントが発生していました(一部不定周期が見られますが)。
> > ※ テキスト添付します。
> >
> > armadillo9にて定周期でイベントを発生させるために、特に設定が必要であれば、助言いただけると大変助かります。
> >
> > タイマー設定部分のソースは下記のとおりです。
> >
> >
> > よろしくお願いします。
> >
> > #define SIGIO_READ SIGRTMIN +1
> >
> > /* timer create */
> > memset( &sigact, 0, sizeof sigact ) ;
> > memset( &sigev, 0, sizeof sigev ) ;
> >
> > sigact.sa_sigaction = timer_handler ;
> > sigact.sa_flags = SA_SIGINFO | SA_RESTART ;
> SA_RESTART は BSDシグナルの挙動を模倣するものなので、
> 必要がなければ、付けなくても良いと思います。
>
> 以下のページが詳しく説明してくれています。
> http://www.nurs.or.jp/~sug/soft/super/signal.htm
>
> > sigemptyset(&sigact.sa_mask);
> > if( sigaction( SIGIO_READ, &sigact, NULL ) < 0 ){
> > return FALSE ;
> > }
> >
> > sigev.sigev_notify = SIGEV_SIGNAL ;
> > sigev.sigev_signo = SIGIO_READ ;
> > if( timer_create( CLOCK_REALTIME, &sigev, &timerId ) < 0 ){
> CLOCK_REALTIME はシステム時刻の影響を受けてしまいますので、
> CLOCK_MONOTONIC の方が良いと思います。
>
> man timer_create を参照してください。
> http://www.kernel.org/doc/man-pages/online/pages/man2/timer_create.2.html
>
> > return FALSE ;
> > }
> >
> > itval.it_interval.tv_sec = 0 ; /* every time up sec */
> > itval.it_interval.tv_nsec = 100 *1000 *1000;/* 100msec */
> > itval.it_value.tv_sec = 10 ; /* first time up sec */
> > itval.it_value.tv_nsec = 0 ; /* 100msec */
> > if( timer_settime( timerId, 0, &itval, NULL ) < 0 ){
> 第2引数に TIMER_ABSTIME を指定すると、絶対間隔でタイマー割り込みが発生します。
> 今回の用途では、指定するべきでしょう。
>
> man timer_settime を参照してください。
> http://linux.die.net/man/3/timer_settime
>
> > return FALSE ;
> > }
> > printf("\n\n complete timer setup\n");
> >
> > while(1){
> > } ;
> >
> > void timer_handler( int signum, siginfo_t *info, void *ctx )
> > {
> > if( signum != SIGIO_READ ){
> > return ;
> > }
> >
> > if( info->si_code != SI_TIMER )
> > return ;
> >
> > int w_start ;
> >
> > printf("\n\n timer_handler() \n" ) ;
> シグナルハンドラ内で printf 関数を使用すると、デッドロックが発生する可能性があります。
>
> 以下のページが詳しく説明してくれています。
> http://d.hatena.ne.jp/yupo5656/20040712/p2
>
> > printf(" signum = %d define = %d \n", signum, SIGIO_READ ) ;
> > w_start = clock() ;
> clock()は、プロセスが使用したプロセッサ時間を得る関数です。
> これでは実時間が分かりませんので、clock_gettime(CLOCK_MONOTONIC, )を使うと良いです。
>
> これも、man ページをご参照ください。
>
> > printf(" time = %d.%03d msec -------------> \n", w_start /1000, w_start %1000 ) ;
>
> 以上の点に気をつけたプログラムを添付します。
> [PC ~]$ arm-linux-gcc -Wall test.c -o test -lrt
> としてコンパイルしてください。
>
> 負荷次第ですが、大体、100msec(0.1 sec)単位で動いています。
> [email@hidden (ttyAM0) /home/ftp/pub]# ./test
>
>
> complete timer setup
> 000: 3282.910287000
> 001: 3283.000127000
> 002: 3283.100066000
> 003: 3283.200049000
> 004: 3283.300041000
> 005: 3283.400039000
> 006: 3283.500127000
> 007: 3283.600092000
> 008: 3283.700051000
> 009: 3283.801311000
> 010: 3283.977836000 <- ここだけ大きくずれてる?
> 011: 3284.000080000 <- TIMER_ABSTIME を付けているので、絶対周期はずれない
> 012: 3284.100060000
> 013: 3284.200045000
> 014: 3284.300037000
> (後略)
>
> --
> Koyo Takenoshita
armadillo メーリングリストの案内