[Armadillo:06915] Re: POSIXタイマー割り込みタイミング

Takenoshita Koyo email@hidden
2011年 3月 23日 (水) 22:20:13 JST


竹之下です。

タイマーの扱いと、シグナルの扱いは難しいですね。
色々な問題が絡み合っているので、インラインで書きます。

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
-------------- next part --------------
テキスト形式以外の添付ファイルを保管しました...
ファイル名: test.c
型:         text/x-csrc
サイズ:     1593 バイト
説明:       無し
URL:        <http://lists.atmark-techno.com/pipermail/armadillo/attachments/20110323/164276c9/attachment.c>


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