#include <stdio.h>
#include <signal.h>
void ALARMhandler(int sig)
{
signal(SIGALRM, SIG_IGN); /* ignore this signal */
printf("Hello");
signal(SIGALRM, ALARMhandler); /* reinstall the handler */
}
int main(int argc, char *argv[])
{
alarm(2); /* set alarm clock */
while (1)
;
printf("All done");
}
プログラムは2秒後に「hello」を出力するはずですが、代わりに出力は「zsh:alarm ./a.out」です
何が起こっているのでしょうか?
最初にアラームハンドラーを設定するのを忘れています。 main()
の開始を次のように変更します。
int main(int argc, char *argv[])
{
signal(SIGALRM, ALARMhandler);
...
また、シグナルハンドラはおそらく何も出力しません。これは、Cライブラリが行末を検出するまで出力をキャッシュするためです。そう:
void ALARMhandler(int sig)
{
signal(SIGALRM, SIG_IGN); /* ignore this signal */
printf("Hello\n");
signal(SIGALRM, ALARMhandler); /* reinstall the handler */
}
実際のプログラムでは、シグナルハンドラからの印刷はあまり安全ではありません。シグナルハンドラは、できる限り少しだけ実行する必要があります。できれば、フラグをここまたはそこに設定するだけにしてください。また、フラグはvolatile
として宣言する必要があります。
main
関数でハンドラーを設定していません。
alarm(2)
を行う前に、main
にsignal(SIGALRM, ALARMhandler);
を入れてください。
それで動作するはずです。
シグナルプロセッサの実行後はwhile(1)ループにとどまるため、「All Done」は出力されないことに注意してください。ループを解除したい場合は、シグナルハンドラーが変更するフラグが必要です。
#include <stdio.h>
#include <signal.h>
/* number of times the handle will run: */
volatile int breakflag = 3;
void handle(int sig) {
printf("Hello\n");
--breakflag;
alarm(1);
}
int main() {
signal(SIGALRM, handle);
alarm(1);
while(breakflag) { sleep(1); }
printf("done\n");
return 0;
}
最初にシグナルハンドラをインストールするわけではありません。
実際に信号を受信する前に、信号を処理することをシステムに伝える必要があるため、信号が来る前にmainからsignal()
を呼び出す必要があります。
int main(int argc, char *argv[])
{
signal(SIGALRM, ALARMhandler); /* install the handler */
alarm(2); /* set alarm clock */
while (1);
}
アンドマールは正統です。これをテストすると、バージョン1が印刷されます(毎秒)。
Hi...
Hi...
Hi...
Hi...
BYE
Hi...
...
バージョン2の印刷(5秒ごと):
Hi...Hi...Hi...Hi...BYE
Hi...Hi...Hi...Hi...BYE
...
したがって、コードは次のとおりです。
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
# define T 5
int flag = T;
void sigalrm_handler(int);
int main(void)
{
signal(SIGALRM, sigalrm_handler);
alarm(1);
while (1);
}
void sigalrm_handler(int sig)
{
if(--flag){
printf("Hi...\n"); /*version 1*/
/*printf("Hi...");*/ /*version 2*/
}else{
printf("BYE\n");
flag=T;
}
alarm(1);
}