web-dev-qa-db-ja.com

シンプルな信号-Cプログラミングおよびアラーム機能

#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」です

何が起こっているのでしょうか?

24
qwer

最初にアラームハンドラーを設定するのを忘れています。 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として宣言する必要があります。

33
Andomar

main関数でハンドラーを設定していません。

alarm(2)を行う前に、mainsignal(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;
}
9
McPherrinM

最初にシグナルハンドラをインストールするわけではありません。
実際に信号を受信する前に、信号を処理することをシステムに伝える必要があるため、信号が来る前にmainからsignal()を呼び出す必要があります。

int main(int argc, char *argv[])
{
  signal(SIGALRM, ALARMhandler);     /* install the handler    */
  alarm(2);                     /* set alarm clock          */
  while (1);
}
5
Arkaitz Jimenez

アンドマールは正統です。これをテストすると、バージョン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);
}
4
alemol