Cライブラリ関数 -sigsuspend()
sigsuspendこの関数は C 標準ライブラリの関数で、現在のシグナルマスクを一時的に置き換え、シグナルを捕捉するまでプロセスを一時停止します。シグナルの待機中にシグナルを失わないアトミックなシグナル待機を実装するためによく使用されます。
構文
int sigsuspend(const sigset_t *mask);
パラメータ
const sigset_t *mask:新しいシグナルマスクを指すポインタ。sigsuspendこのシグナルマスクで現在のシグナルマスクを置き換え、シグナルを捕捉した後に元のシグナルマスクを復元します。
戻り値
sigsuspendこの関数は常に -1 を返し、errnoに設定しEINTR、関数がシグナルによって中断されたことを示します。
例
以下は、sigsuspendsigsuspend() 関数を使用して特定のシグナルを待つサンプルプログラムです。このプログラムはシグナルハンドラを設定し、次に sigsuspend() を使用してsigsuspendプロセスを一時停止し、シグナルを捕捉するまで待ちます。
例
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
volatile sig_atomic_t flag = 0;
// カスタムシグナルハンドラ関数
void handle_sigint(int sig) {
printf("Caught signal %d\n", sig);
flag = 1;
}
int main() {
struct sigaction sa;
sigset_t new_mask, old_mask, wait_mask;
// SIGINT のハンドラを handle_sigint に設定
sa.sa_handler = handle_sigint;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGINT, &sa, NULL) == -1) {
perror("sigaction");
return 1;
}
// シグナルセットを初期化
sigemptyset(&new_mask);
sigaddset(&new_mask, SIGINT);
// SIGINT シグナルをブロック
if (sigprocmask(SIG_BLOCK, &new_mask, &old_mask) == -1) {
perror("sigprocmask");
return 1;
}
// 待機シグナルセットを初期化
sigemptyset(&wait_mask);
printf("Waiting for SIGINT...\n");
// sigsuspend を使用してプロセスを一時停止し、シグナルを待つ
while (!flag) {
if (sigsuspend(&wait_mask) != -1) {
perror("sigsuspend");
return 1;
}
}
// 元のシグナルマスクを復元
if (sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) {
perror("sigprocmask");
return 1;
}
printf("Exiting...\n");
return 0;
}
#include <signal.h>
#include <unistd.h>
volatile sig_atomic_t flag = 0;
// カスタムシグナルハンドラ関数
void handle_sigint(int sig) {
printf("Caught signal %d\n", sig);
flag = 1;
}
int main() {
struct sigaction sa;
sigset_t new_mask, old_mask, wait_mask;
// SIGINT のハンドラを handle_sigint に設定
sa.sa_handler = handle_sigint;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGINT, &sa, NULL) == -1) {
perror("sigaction");
return 1;
}
// シグナルセットを初期化
sigemptyset(&new_mask);
sigaddset(&new_mask, SIGINT);
// SIGINT シグナルをブロック
if (sigprocmask(SIG_BLOCK, &new_mask, &old_mask) == -1) {
perror("sigprocmask");
return 1;
}
// 待機シグナルセットを初期化
sigemptyset(&wait_mask);
printf("Waiting for SIGINT...\n");
// sigsuspend を使用してプロセスを一時停止し、シグナルを待つ
while (!flag) {
if (sigsuspend(&wait_mask) != -1) {
perror("sigsuspend");
return 1;
}
}
// 元のシグナルマスクを復元
if (sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) {
perror("sigprocmask");
return 1;
}
printf("Exiting...\n");
return 0;
}
このプログラムをコンパイルして実行すると、出力は次のようになります:
Waiting for SIGINT...
Ctrl+C を押すと(SIGINTSIGINT シグナルを送信すると)、出力は次のようになります:
Caught signal 2 Exiting...
プログラムはSIGINTシグナルを捕捉し、シグナルハンドラ関数を実行しhandle_sigint、設定flagを 1 にし、メインループを終了してプログラムを終了します。
説明
sigset_t new_mask, old_mask, wait_mask;:3 つのシグナルセットを定義して、シグナルマスクを制御します。- 使用して
sigprocmask関数SIGINTでシグナルをブロックし、元のシグナルマスクを保存します。 - 使用して
sigsuspend関数でプロセスを一時停止し、シグナルを待ちます。sigsuspend現在のシグナルマスクを一時的に置き換えるるwait_mask、シグナルを捕捉した後に元のシグナルマスクを復元します。 - シグナルを捕捉した後、元のシグナルマスクを復元し、プログラムを続行します。
注意事項
sigsuspend信頼性の高いシグナル待機機構を実装して、シグナルがマスクされている間に失われるのを防ぐためによく使用されます。- シグナルハンドラ関数はできるだけ短くする必要があります。シグナルを処理している間は他のシグナルがブロックされるからです。長時間実行されるシグナルハンドラ関数は、プログラムのリアルタイム性に影響を与える可能性があります。
C標準ライブラリ - <signal.h>