1

私は現在、情報を処理する無限ループを持つサーバー上にCで作成したプログラムを持っています。各ループは、完了するのに約5分かかります。シェルスクリプトに次の機能を持たせたいです。

  • Cプログラムを終了します
  • ソースを作成
  • プログラムを実行する

問題は、ctrl + cのようなことをせずにCプログラムを終了するように指示する方法がわからないことです。むしろ、現在作業中の情報の処理を終了してから終了したいと思います。

4

3 に答える 3

4

プロセスにビジネスを終了してクリーンに終了するように指示するPOSIXの標準的な方法は、SIGTERMシグナルを送信することです。アプリケーションによっては、で終了することが適切な場合とそうでない場合がありますSIGINT。これは、プロセスを終了するのではなく、中断することを意味します。(Control-cは送信しますSIGINT。)

タイトなループに旗を立ててみてください。簡単に終了できるときにフラグを確認しますが、それでもすぐに終了するのに十分な頻度です。あなたの場合、を受信するとSIGTERMすぐにシステムログにメッセージが表示され、5分以内に終了することが約束されます。

シグナルハンドラは次のようになります。

static int signalled;  // if nonzero, what signal have we been sent?

static void SignalHandler(int signum) {
  signalled = signum;
}

I / O操作のたびにグローバルstatic変数をチェックしますsignalled。つまり、1秒間に何度もチェックします。

シグナルをキャッチして復元するための私のコードは次のとおりです。

static __sighandler_t sh, si, st;

static void catch_signals(void) {
  if ((sh = signal(SIGHUP, SignalHandler)) == SIG_IGN) signal(SIGHUP, SIG_IGN);
  if ((si = signal(SIGINT, SignalHandler)) == SIG_IGN) signal(SIGINT, SIG_IGN);
  if ((st = signal(SIGTERM, SignalHandler)) == SIG_IGN) signal(SIGTERM, SIG_IGN);
  signalled = 0;
}

static void restore_signals(void) {
  signal(SIGHUP, sh);
  signal(SIGINT, si);
  signal(SIGTERM, st);
}

(このコードはライブラリからのものであるため、見つけたままにしておくように特に注意しています。)

ボーナストリック:時間が経過すると(これはテレビ録画ライブラリです)、タイマーが設定されるだけでsignalled = SIGTERM、同じロジックがレコーダーを正常に終了するために使用されます。

于 2012-08-11T14:03:34.767 に答える
3

ctrl + cのように、itelを終了する前に、現在作業中の情報の処理を終了したほうがいいです。

SIGINTまたは必要なもののシグナルハンドラーを確立し、受信後にクリーンアップを実行します。ただし、ハンドラー自体でクリーンアップを実行しないでください。

volatile sig_atomic_t do_cleanup = 0;
void handler(int sig)
{
    do_cleanup = 1;
}

次に、メインループで、必要に応じてテストdo_cleanupして終了する必要があります。EINTRまだエラーを処理していない場合は、エラーを適切に処理する際にも注意する必要があります。

于 2012-08-11T13:55:06.233 に答える
1

シェルから信号を送信する方法は次のとおりです。

http://bash.cyberciti.biz/guide/Sending_signal_to_Processes

または単にman kill

信号に反応する方法は次のとおりです。

http://www.cs.cf.ac.uk/Dave/C/node24.html#SECTION002400000000000000000

于 2012-08-11T14:04:40.993 に答える