ここにはvolatile sig_atomic_t
を使用する簡単なおもちゃプログラムがあります。シグナルハンドリングのコンテキストで、どの変数がsig_atomic_tである必要がありますか?
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#define UNUSED(x) (void) (x)
volatile sig_atomic_t quit;
void sigusr1_handler(int sig)
{
UNUSED(sig);
write(1, "handler\n", 8);
quit = 1;
}
int main()
{
struct sigaction sa;
sa.sa_handler = sigusr1_handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGUSR1, &sa, NULL) == -1) {
perror("sigaction");
return 1;
}
quit = 0;
while (!quit)
;
printf("Exiting ...\n");
return 0;
}
私はvolatile sig_atomic_t
は、この特定のプログラムでquit
変数のために必要である理由私が知っていると思います。
volatile
を指定しないと、コンパイラはwhile (!quit) ;
を無限ループに最適化することがあります。quit
を変更するループが見つからないため、quit
は常に0
のままであるとみなします。quit
への更新またはquit
の読み取りは、1回のマシン命令で実行する必要があります。quit
を更新または読み取るために複数のマシン命令が必要な場合、更新中にシグナルハンドラが呼び出された場合、シグナルハンドラの読み込みには一貫性のない値がquit
になることがあります。
これまで正しいですか?そうでない場合は、あなたの答えで私を修正してください。
信号処理のコンテキストでsig_atomic_t
が必要な場合の一般化されたルールを学びたいと思います。 Jonathan Lefflerはこのコメントで、一般化を提供することは容易ではないと説明した。
変数をC標準の観点からsig_atomic_t
と定義する必要がある既知のシナリオのリストを提供できますか?網羅的なリストである必要はありません。あまり経験の浅い開発者が参照することができるリストで、C言語のソフトウェアに信号処理コードを記述することができます。
'一般化'は容易ではありません。シグナルハンドリングのセマンティクスは、異なるマシンでは異なります。 C標準は、シグナルハンドラでできることを信じられないほど制限しています。 POSIXはもっと寛大ですが、依然として厳しい制限があります(例えば、 'strlen()'は安全に使うことはできませんが、 'write()'はできます)。 Windowsのルールはおそらくもう一度異なっています。 'sigaction()'や 'signal()'や他のAPIを使う予定ですか?ポイント(1)に関して、「はい」。ポイント(2) "多かれ少なかれ"(問題のない程度に近い)。 –
@JonathanLefflerコメントありがとうございます。私は質問の範囲を絞り込んだ:(1)変数が 'sig_atomic_t'として定義される必要がある既知のシナリオのリストを要求する(完全なリストである必要はない)(2)良い答えを求めるC標準(POSIXではなく)用です。 –