C++ 信号処理


シグナルは、オペレーティングシステムによってプロセスに送信される割り込みであり、プログラムを早期に終了させます。 UNIX、LINUX、Mac OS X、または Windows システムでは、Ctrl+C を押すと割り込みを生成できます。

一部の信号はプログラムでキャプチャできませんが、次の表にリストされている信号はプログラムでキャプチャでき、信号に基づいて適切なアクションを実行できます。これらのシグナルは、C++ ヘッダー ファイル で定義されます。

Signal
SIGABRTプログラムの異常終了(abortの呼び出しなど)について説明します。
SIGFPEゼロによる除算やオーバーフローを引き起こす演算など、不正な算術演算。
SIGILL 不正な指示を検出します。
SIGINTインタラクティブなアテンションシグナルを受信しました。
SIGSEGVメモリへの不正なアクセス。
SIGTERM プログラムに送信された終了リクエスト。

signal() 関数

C++ 信号処理ライブラリは、予期しないイベントをキャプチャするための signal 関数を提供します。以下は signal() 関数の構文です:

void (*signal (int sig, void (*func)(int)))(int);

この関数は 2 つのパラメーターを受け取ります。最初のパラメーターは信号の番号を表す整数で、2 番目のパラメーターは信号処理関数へのポインターです。

signal() 関数を使用して SIGINT 信号をキャプチャする簡単な C++ プログラムを作成しましょう。プログラム内でどのようなシグナルをキャッチしたい場合でも、signal 関数を使用してシグナルを登録し、シグナル ハンドラーに関連付ける必要があります。次の例を見てください:

#include <iostream>
#include <csignal>

using namespace std;

void signalHandler( int signum )
{
    cout << "Interrupt signal (" << signum << ") received.\n";

    // 清理并关闭
    // 终止程序  

   exit(signum);  

}

int main ()
{
    // 注册信号 SIGINT 和信号处理程序
    signal(SIGINT, signalHandler);  

    while(1){
       cout << "Going to sleep...." << endl;
       sleep(1);
    }

    return 0;
}

上記のコードがコンパイルされて実行されると、次の結果が生成されます:

Going to sleep....
Going to sleep....
Going to sleep....

次に、Ctrl+C を押してプログラムを中断すると、プログラムがシグナルをキャッチしていることがわかります。プログラムは以下を出力して終了します:

Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.

raise() 関数

次の構文で整数の信号番号をパラメーターとして受け取る関数 raise() を使用して信号を生成できます。

int raise (signal sig);

ここで、 sig が送信されるシグナルの番号。これらのシグナルには、SIGINT、SIGABRT、SIGFPE、SIGILL、SIGSEGV、SIGTERM、SIGHUP が含まれます。以下は、 raise() 関数を使用して内部でシグナルを生成する例です:

#include <iostream>
#include <csignal>

using namespace std;

void signalHandler( int signum )
{
    cout << "Interrupt signal (" << signum << ") received.\n";

    // 清理并关闭
    // 终止程序 

   exit(signum);  

}

int main ()
{
    int i = 0;
    // 注册信号 SIGINT 和信号处理程序
    signal(SIGINT, signalHandler);  

    while(++i){
       cout << "Going to sleep...." << endl;
       if( i == 3 ){
          raise( SIGINT);
       }
       sleep(1);
    }

    return 0;
}

上記のコードがコンパイルされて実行されると、次の結果が生成され、自動的に終了します:

Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.