シグナルとは
プロセスに対して非同期に通知を送る仕組み。
ソフトウェアの割り込み機能。
強制終了、再起動、一時停止など
C++での使用
ライブラリ
csignal
signal()
signal(int signum, void (*handler)(int));
-
signum: シグナル番号 -
handler: 受信時に実行される関数
シグナルをキャッチすると関数が実行される。
signal()の挙動は環境依存な部分がある。
後述のsigaction()の使用が推奨されている
ハンドラ関数の制約
-
void型 -
int型の引数を持つ(この引数にはシグナル番号が格納される)
async-signal-safeな処理のみ使用できる。
使用例
#include <iostream>
#include <csignal>
void signal_handler(int signum){
// 処理
}
int main() {
std::signal(SIGINT, signal_handler);
//...
return 0;
}
sigaction()
sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
-
signum: シグナル番号 -
act: 新しく設定するシグナル動作 -
oldact: 以前の設定を受け取る
act、oldactにはnullptrを設定できる。(前の設定を引き継ぐ)
signal()よりも詳細な制御が可能な関数。(推奨)
またsignal()同様、async-signal-safeな処理のみ使用できる。
struct sigaction
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t*, void*);
sigset_t sa_mask;
int sa_flags;
};
sa_handler()
void (*sa_handler)(int);
通常のシグナルハンドラ。
signal()のハンドラ関数と同じ。
sa_sigaction()
void (*sa_sigaction)(int, siginfo_t*, void*);
拡張のシグナルハンドラ。
sa_flagsにSA_SIGINFOを指定した場合に使用される。
- 第一引数: シグナル番号
-
siginfo_t*: 送信元PID、シグナルの原因など - 第三引数: ユーザーコンテキスト
sa_mask
sigset_t sa_mask;
ハンドラ実行中にブロックするシグナル集合を指定する。
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, signum);
ハンドラ実行中signumが無効化される。
sa_flags
int sa_flags;
シグナル処理のオプションを指定する。
主に
-
SA_RESTART
シグナルで中断されたシステムコールを自動再開する -
SA_SIGINFO
sa_sigactionを使用する -
SA_NODEFER
自分自身のシグナルをブロックしない(デフォルトではブロックされる)
使用例
#include <csignal>
#include <cstring>
void handler(int sig) {
// 処理
}
int main() {
struct sigaction act;
std::memset(&act, 0, sizeof(act));// 未初期化フィールドによる未定義動作を防ぐため
act.sa_handler = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGINT, &act, nullptr);
}
raise()
raise(int signum);
-
signum: シグナル番号
シグナルを意図的に送信する。
使用例
#include <csignal>
int main() {
std::raise(SIGINT);
}