C++教科書/標準ライブラリ編/<csignal>の章
編集概要
編集<csignal>
ヘッダーはプログラムにおけるシグナル処理を行うための機能を提供します。シグナルとは、特定の事象が発生したことをオペレーティングシステムからプロセスに通知するために使われるメカニズムです。代表的なシグナルには、割り込み(SIGINT)、セグメンテーション違反(SIGSEGV)、算術演算例外(SIGFPE)などがあります。
型
編集sig_atomic_t
シグナルハンドラ内で安全にアクセスできる最小のロックフリー型です。この型への参照は、シグナルハンドラが呼び出される間は常に代入可能です。
マクロ
編集- シグナル種別マクロ
-
- SIGABRT
- 異常終了シグナル
- SIGFPE
- 算術演算例外が発生したことを示す
- SIGILL
- 無効命令が実行されたことを示す
- SIGINT
- 端末からの割り込みを示す
- SIGSEGV
- 無効なメモリ参照を示す
- SIGTERM
- 終了要求を示す
- シグナルハンドラ指定用マクロ
-
- SIG_DFL
- デフォルトの動作を行う
- SIG_IGN
- シグナルを無視する
関数
編集- signal(int sig, sig_handler func)
- 指定のシグナル(sig)が発生した際に呼び出されるハンドラ関数(func)を設定します。funcにSIG_DFLを渡すとデフォルトの動作に、SIG_IGNを渡すと無視するように設定できます。正常場合は以前のハンドラを返し、エラー時はSIG_ERRを返します。
- raise(int sig)
- 指定のシグナル(sig)を発生させ、現在設定されているハンドラを呼び出します。
シグナルハンドラの作成
編集シグナルハンドラは以下のプロトタイプを持つ関数として実装します。
void handler(int sig) { // ハンドラ処理 }
ハンドラ内では、シグナルセーフでない関数(malloc、printf、exit等)の呼び出しは避ける必要があります。また、グローバル変数へのアクセスにも注意が必要です。sig_atomic_t型の変数を介して安全にグローバル状態にアクセスできます。
実践例
編集- 割り込みハンドラの実装
#include <csignal> #include <cstdio> volatile sig_atomic_t gSignalStatus; void handler(int sig) { gSignalStatus = sig; } auto main() -> int { gSignalStatus = 0; signal(SIGINT, handler); // 処理ループ while (gSignalStatus != SIGINT) { std::puts("Running..."); // 処理 } std::puts("Interrupted!"); return 0; }
- シグナルを使った並列化
#include <csignal> #include <cstdio> volatile sig_atomic_t gCounter; void handler(int /*unused*/) { ++gCounter; } auto main() -> int { gCounter = 0; signal(SIGINT, handler); // 割り込みハンドラ設定 // 並列処理のためにSIGINTを発生 for (int i = 0; i < 1000000; ++i) { raise(SIGINT); } std::puts("gCounter = {}", gCounter); return 0; }
まとめ
編集<csignal>
ヘッダーはシグナルハンドリング機能を提供し、プログラムの例外処理や並列化、割り込み処理などに利用できます。シグナルセーフな実装に注意が必要ですが、C++プログラムをさまざまな環境で安全かつ効率的に動作させるための重要な機能です。