2016-04-30 14 views
0

GPSモジュールからデータを取得して処理するRaspberry-Pi(linux)で動作するプログラムを開発しています。Cでシグナルを使用する方法、タイマー終了時にプログラムを停止し続ける方法

今のところ、プログラムはGPSデータを取り込み、GPSモジュールの周波数でストリーミングされたwhile(1)ループを中心にしています。

しかし、私はwhile(1)が非常に効率的な解決策ではないことを知っています(このRPiは後で無人機に座る予定です)。

私はタイマーを設定したいと思います。タイマーが終了したときだけ、プログラムはGPSデータを取得しますか?理想的には、タイマーが終了するまでプログラムが完全に停止し、CPUが時間/エネルギーを無駄にしないようにします。

sigaction()コールでSIGSTOPシグナルが許可されていない場合は、どうすればできますか?あなたのループでは

void timer_handler(int signum){ 
    /* what can I do to make a program stop and coninue, 
     so that no CPU cycles are devoted to this program until 
     the timer is elapsed ? (SIGSTOP is not allowed) */ 
} 

int main(int argc, char** argv){ 

    struct sigaction sigAct; 
    struct itimerval timer; 
    sa.sa_handler = &timer_handler; 

    // SIGALRM is only a place holder here.. 
    sigaction(SIGALRM, &sigAct, NULL); 

    /* Here would be some timer.it_value, timer.it_interval stuff, 
    setting it to some arbitrary time */ 

    setitimer(ITIMER_REAL, &timer, NULL); 

    /* Main program loop here */ 
    while(1){ 
     // process GPS data. 
     // instead of while(1), I'd like this loop to run only when 
     // the timer ends. 
    } 

} 
+0

「スリープ」を呼び出すことはできませんか? – kaylum

+0

私はちょうど秒より大きな解像度が必要です。 私は 'nanosleep()'を認識していますが、この関数を呼び出すと、このプログラムの実行を完全に放棄するかどうかわかりません。私が見つけることができる限り。 –

+1

はいそれは完全にプロセスを中断します。自分自身をチェックするには、nanosleepを呼び出してプロセスの状態をチェックするだけです。 – kaylum

答えて

1

、ちょうどpause()を呼び出します。それはブロックされ、シグナルが受信されたときにのみ戻るので、コードを実行して、再度ループし、繰り返すことができます。 SIGALRMがプログラムを終了するのを防ぐためにシグナルハンドラが必要ですが、何もする必要はありません。関数本体を空のままにしておくことができます。例えば

#define _POSIX_C_SOURCE 200809L 

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <signal.h> 
#include <sys/time.h> 

void timer_handler(int signum) 
{ 
    (void) signum;  /* Avoids warning for unused argument */ 
} 

int main(void) 
{ 
    struct sigaction sa; 
    sa.sa_handler = timer_handler; 
    sa.sa_mask = 0; 
    sa.sa_flags = 0; 
    sigaction(SIGALRM, &sa, NULL); 

    struct itimerval timer; 
    timer.it_value.tv_sec = 1; 
    timer.it_value.tv_usec = 0; 
    timer.it_interval.tv_sec = 1; 
    timer.it_interval.tv_usec = 0; 
    setitimer(ITIMER_REAL, &timer, NULL); 

    while (1) { 
     pause(); 
     printf("Timer expired - get GPS data.\n"); 
    } 

    return 0; 
} 

は出力が得られます。

[email protected]:~/src/sandbox$ ./alarm 
Timer expired - get GPS data. 
Timer expired - get GPS data. 
Timer expired - get GPS data. 
Timer expired - get GPS data. 
Timer expired - get GPS data. 
Timer expired - get GPS data. 
Timer expired - get GPS data. 
Timer expired - get GPS data. 
^C 
[email protected]:~/src/sandbox$ 

それはかなり粗溶液です。タイマー間隔よりも実行に時間がかかる可能性がある場合は、状況が信頼できなくなり、信号をスキップすることがあります。あなたはこれを気にするかもしれません。より洗練されたアプローチでは、SIGALRMの受信をブロックしてから、ブロック解除するシグナルマスクを使用してsigsuspend()を呼び出すことができます。アンブロッキングとシグナルの待機がアトミックな操作であることを知っていれば安全です。ここではそのアプローチの例です:

#define _POSIX_C_SOURCE 200809L 

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <signal.h> 
#include <sys/time.h> 

void timer_handler(int signum) 
{ 
    static const char msg[] = "Handler was called.\n"; 
    write(STDIN_FILENO, msg, sizeof(msg) - 1); 
    (void) signum; 
} 

int main(void) 
{ 
    struct sigaction sa; 
    sa.sa_handler = timer_handler; 
    sa.sa_mask = 0; 
    sa.sa_flags = 0; 
    sigaction(SIGALRM, &sa, NULL); 

    struct itimerval timer; 
    timer.it_value.tv_sec = 1; 
    timer.it_value.tv_usec = 0; 
    timer.it_interval.tv_sec = 1; 
    timer.it_interval.tv_usec = 0; 
    setitimer(ITIMER_REAL, &timer, NULL); 

    sigset_t old_mask, block_mask; 
    sigemptyset(&block_mask); 
    sigaddset(&block_mask, SIGALRM); 
    sigprocmask(SIG_BLOCK, &block_mask, &old_mask); 

    sleep(3); /* To demonstrate signal handler won't be 
        called until sigsuspend() is called, timer 
        is firing every second while we're sleeping */ 

    while (1) { 
     sigsuspend(&old_mask); 
     printf("Timer expired - get GPS data.\n"); 
    } 

    return 0; 
} 

出力で:

[email protected]:~/src/sandbox$ ./alarm2 
Handler was called. 
Timer expired - get GPS data. 
Handler was called. 
Timer expired - get GPS data. 
Handler was called. 
Timer expired - get GPS data. 
Handler was called. 
Timer expired - get GPS data. 
Handler was called. 
Timer expired - get GPS data. 
Handler was called. 
Timer expired - get GPS data. 
^C 
[email protected]:~/src/sandbox$ 

エラーチェックは、上記の例では簡略化のために省略されているが、あなたのコードはもちろん、すべてのシステムコールのためにそれを含める必要があります。

関連する問題