web-dev-qa-db-ja.com

LinuxでのCtrl + C割り込みイベント処理

C++を使用し、Linux GNU C Compilerを使用してコンパイルするアプリケーションを開発しています。ただし、ユーザーがスクリプトを中断するときに関数を呼び出したい CtrlC キー。私は何をすべきか?どんな答えでも大歓迎です。

25
mozcelikors

を押すと Ctr + C、オペレーティングシステムは signal をプロセスに送信します。多くのシグナルがあり、そのうちの1つはSIGINTです。 SIGINT(「プログラム割り込み」)は終了シグナルの1つです。

終了シグナルにはさらにいくつかの種類がありますが、SIGINTの興味深い点は、プログラムで処理(キャッチ)できることです。 SIGINTのデフォルトアクションはプログラムの終了です。つまり、プログラムがこの信号を特に処理しない場合、次を押します。 Ctr + C プログラムはデフォルトのアクションとして終了します。

シグナルのデフォルトのアクションを変更するには、キャッチするシグナルを登録する必要があります。 (少なくともPOSIXシステムで)Cプログラムにシグナルを登録するには、2つの関数があります

  1. signal(int signum、sighandler_t handler);
  2. sigaction(int signum、const struct sigaction * act、struct sigaction * oldact);

これらの関数には、ヘッダー signal.h をCコードに含める必要があります。コメント付きの以下のsignal関数の簡単な例を提供しました。

#include <stdio.h>
#include <stdlib.h>
#include <signal.h> //  our new library 
volatile sig_atomic_t flag = 0;
void my_function(int sig){ // can be called asynchronously
  flag = 1; // set flag
}

int main(){
  // Register signals 
  signal(SIGINT, my_function); 
  //      ^          ^
  //  Which-Signal   |-- which user defined function registered
  while(1)  
    if(flag){ // my action when signal set it 1
        printf("\n Signal caught!\n");
        printf("\n default action it not termination!\n");
        flag = 0;
    }     
  return 0;
}  

注:シグナルハンドラでは safe/authorized functions のみを呼び出す必要があります。たとえば、 シグナルハンドラでprintfを呼び出さないでください

このコードをgccでコンパイルして、シェルから実行できます。コードには無限ループがあり、を押してSIGINT信号を送信するまで実行されます Ctr + C

55
Grijesh Chauhan

タイピング CtrlC 通常、シェルはSIGINTをプログラムに送信します。そのシグナルのハンドラーを( signal(2) または sigaction(2) を介して)追加すると、いつでも好きなことができます CtrlC が押されます。

代わりに、プログラムが終了する前にクリーンアップのみを行う場合は、 atexit(3) を使用して終了ハンドラーを設定する方が適切な場合があります。

11
Carl Norum

シグナルマクロを使用できます。

対処方法の例を次に示します。

#include <signal.h>
#include <stdio.h>
void sigint(int a)
{
    printf("^C caught\n");
}
int main()
{
    signal(SIGINT, sigint);
    for (;;) {}
}

サンプル出力:

Ethans-MacBook-Pro:~ phyrrus9$ ./a.out
^C^C caught
^C^C caught
^C^C caught
^C^C caught
^C^C caught
4
phyrrus9