2-7. シグナル処理

公開日: 10:48 2. 応用編/2-7. シグナル処理

シグナルはオペレーティングシステムによってプロセスへ送られる割り込みであり、プログラムを途中で終了させることができます。 UNIX、LINUX、Mac OS X、Windowsではコントロールキーとcを押すことで割り込みを生成できます。

プログラムで補足できないシグナルもありますが、以下のリストはプログラムで補足できるものであり、シグナルに基づいた適切な行動を取ることが可能です。これらのシグナルはC++では<csignal>ヘッダファイルで定義されています。

シグナル説明
SIGABRTabort(休止)呼び出しなどのプログラムの異常終了
SIGFPE0除算やオーバーフローになる命令のような誤った算術命令
SIGILL不正な命令の検出
SIGINTインタラクティブな注意信号の受信
SIGSEGV記憶領域への不正アクセス
SIGTERMプログラムに送られた終了リクエスト


シグナル関数 signal()

C++のシグナル制御ライブラリは予期せぬ出来事を把握するためにsignal関数を備えています。次の構文はsignal()関数です。
void (*signal (int sig, void (*func)(int)))(int);

この関数は2つの引数を取ります。1つ目はシグナル番号を表す整数で、2つ目はシグナル制御関数へのポインタとなります。

signal()関数を使ってSIGINTを補足するC++プログラムを書いてみましょう。どのようなシグナルでもプログラムで補足したいものは、そのシグナルをシグナル関数を使って登録する必要があり、さらにシグナルハンドラと関連付けます。
#include <iostream>
#include <csignal>
#include <cstdllib>  //exit()
#include <unistd.h>  //sleep()

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>
#include <cstdllib>  //exit()
#include <unistd.h>  //sleep()

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.

  • ?±??G???g???[?d????u?b?N?}?[?N???A

0 件のコメント :

コメントを投稿