2011-08-12 2 views
1

割り込み信号を受信した後にデータを保存できるようにC/C++プログラムを設計する方法。プログラムを実行してデータを保存する割り込みを実行する

私は実行を終了する前に、(Ctrl-Cを押して)強制終了する必要のある長いプログラムを持っています。終了時に実行するのではなく、強制終了すると、プログラムはいくつかの変数をディスクに保存することができるはずです。私はいくつかの大きなLinuxの本を持っていますが、どこから始めるべきかについてはあまりよく分かりません。調理法のレシピはとても役に立ちます。

ありがとうございます!

答えて

4

これを行うには、プログラムが何をしているのかを彼に知らせるグローバル変数などのプログラムを見せておく必要があります。

たとえば、長期実行中のプログラムがループを実行すると仮定、あなたはそれを行うことができます。g_shouldAbortと

g_shouldAbort = 0; 
while(!finished) 
{ 
    // (do some computing) 

    if (g_shouldAbort) 
    { 
     // save variables and stuff 
     break; // exit the loop 
    } 
} 

グローバル揮発性変数として定義し、そのように:

static volatile int g_shouldAbort = 0; 

( "volatile"と宣言することは非常に重要です。そうでなければ、誰もループに書き込まないので、コンパイラは、(g_shouldAbort)が常にfalseになり、optiそれを離れてマイズ)

、その後、例えば、他のユーザーが提案信号 APIを使用して、あなたがそれを行うことができます。

void signal_handler(int sig_code) 
{ 
    if (sig_code == SIGUSR1) // user-defined signal 1 
     g_shouldAbort = 1; 
} 

(あなたはもちろんのこのハンドラを登録する必要があり、参照をhere。あなたがプログラムにSIGUSR1信号を「送信」すると

signal(SIGUSR, signal_handler); 

、(で例えばコマンドを殺す)、g_shouldAbortは1に設定され、あなたのプログラムは、そのコンピューティングを停止します。

このヘルプが必要です。

注:この手法は簡単ですが粗いです。シグナルとグローバル変数を使用すると、他のユーザーが概説したように、複数のスレッドを使用することが難しくなります。

0

signal(2)またはsigaction(2)を使用して、SIGINT信号に関数ポインタを割り当て、そこでクリーンアップします。

4

あなたがしたいことは自明ではありません。まず、signalまたはsigactionを使用してSIGINT(C-c)のシグナルハンドラをインストールしてから、のハード部分が起動します。

主な問題は、シグナルハンドラでは、async-signal-safe functions(またはreentrant関数)のみ呼び出すことができるということです。ほとんどのライブラリ関数は、確実にリエントラントと見なすことはできません。たとえば、stdioの機能、mallocfreeなど多くのものはリエントラントではありません。

どのようにこれを処理しますか?ハンドラ内でflagを設定してください(一部のグローバル変数done1に設定してください)、EINTRのエラーを見てください。の外部でクリーンアップを実行することは安全です。

0

は、あなたがしようとしているどのような奇妙なデータ

+0

for C++あなたはboost :: call_onceを考慮することができます – Nelstaar

3

を救うあなたのファイルの書き込みを終える前に、あなたのプロセスは、2つの以上の信号を取得した場合、あなたのあなたの保存機能

// somewhere in main 
signal(SIGTERM, signalHandler); 
signal(SIGINT, signalHandler); 

void saveMyData() 
{ 
    // save some data here 
} 

void signalHandler(int signalNumber) 
{ 
    static pthread_once_t semaphore = PTHREAD_ONCE_INIT; 
    std::cout << "signal " << signalNumber << " received." << std::endl; 
    pthread_once(& semaphore, saveMyData); 
} 

に一度だけ入力してくださいチェックポイント/再起動のループルに該当します。

チェックポイント/再起動に信号駆動方式を使用すると、いくつかの大きな問題があります。 1つは、信号ハンドラは非常にコンパクトで非常にプリミティブでなければならないということです。シグナルハンドラ内にチェックポイントを書き込むことはできません。別の問題は、信号が送信されるときに、実行状態のプログラムがのいずれかの場所にある可能性があります()。そのランダムな場所は、ほとんどの場合、チェックポイントを破棄できる安全なポイントではありません。さらに別の問題は、アプリケーション側のチェックポイント/再起動機能でプログラムを整える必要があることです。

独自のチェックポイント/再起動機能を使用するのではなく、すでに存在する無料のものを使用することをお勧めします。 linuxのgdbは、チェックポイント/リスタート機能を提供します。もう1つはDMTCPです(http://dmtcp.sourceforge.net/index.htmlを参照)。

関連する問題