0

現在、いくつかのシグナルハンドラをセットアップしようとしています。具体的には、デフォルトの処理に戻す SIGQUIT ハンドラーをインストールしたいのですが、n 秒後に SIGQUIT ハンドラーを再インストールします。

最初にシグナル ハンドラを main() にインストールしたときは問題ありませんが、コードを追加して SIGQUIT ハンドラを SIGALRM ハンドラに再インストールしようとすると、コンパイル時に次のエラー メッセージが表示され続けます。

ish.c: In function ‘SIGALRM_Handler’:
ish.c:42: error: ‘SIGQUIT_Handler’ undeclared (first use in this function)
ish.c:42: error: (Each undeclared identifier is reported only once
ish.c:42: error: for each function it appears in.)

関連するコードのスニペットを次に示します。アラームがトリガーされたときにいつでも SIGQUIT ハンドラーを再インストールしたいだけですが、どうすればよいかわかりません。

/* SIGALRM handler */

static void SIGALRM_Handler(int iSig)
{
   void (*pfRet)(int);
   /* reinstall SIGQUIT handler */
   pfRet = signal(SIGQUIT, SIGQUIT_Handler);
   if (pfRet == SIG_ERR) { perror("SIGQUIT_Handler"); exit(EXIT_FAILURE); }
}

/*--------------------------------------------------------------------*/

/* SIGQUIT handler */

static void SIGQUIT_Handler(int iSig)
{
   void (*pfRet)(int);
   /* Print message followed by shell prompt */
   printf("Type Ctrl-\\ again within 5 seconds to exit\n");
   printf("------------------------------------\n");
   printf("%c ", '%');
   fflush(NULL);
   /* install default SIGQUIT handling */
   pfRet = signal(SIGQUIT, SIG_DFL);
   if (pfRet == SIG_ERR) { perror("SIGQUIT_Handler"); exit(EXIT_FAILURE); }
   /* set alarm for 5 seconds later */
   alarm(5);
}

...

int main(int argc, char **argv)
{
   FILE *psFile;
   void (*pfRet)(int);
   sigset_t sSet;
   int iRet;
   assert(argv != NULL);
   /* make sure needed signals are not blocked */
   sigemptyset(&sSet);
   sigaddset(&sSet, SIGINT);
   sigaddset(&sSet, SIGQUIT);
   sigaddset(&sSet, SIGALRM);
   iRet = sigprocmask(SIG_UNBLOCK, &sSet, NULL);
   if (iRet == -1) { perror(argv[0]); exit(EXIT_FAILURE); }
   /* install SIGINT handler */
   pfRet = signal(SIGINT, SIGINT_Handler);
   if (pfRet == SIG_ERR) { perror(argv[0]); exit(EXIT_FAILURE); }
   /* install SIGALRM handler */
   pfRet = signal(SIGALRM, SIGALRM_Handler);
   if (pfRet == SIG_ERR) { perror(argv[0]); exit(EXIT_FAILURE); }
   /* install SIGQUIT handler */
   pfRet = signal(SIGQUIT, SIGQUIT_Handler);
   if (pfRet == SIG_ERR) { perror(argv[0]); exit(EXIT_FAILURE); }
   /* check for configuration file */
   if (argc > 2)
   {
      fprintf(stderr, "Usage: ish [configfile]\n");
      exit(EXIT_FAILURE);
   }
   else if (argc == 2)
   {
      psFile = fopen(argv[1], "r");
      if (psFile != NULL)
      {
         handleProcess(psFile);
      }
      else
      {
         fprintf(stderr, "ish: ");
         perror(argv[1]);
      }
   }
   for(;;)
   {
      handleProcess(stdin);
   }
   return 0;
}
4

1 に答える 1

2

SIGQUIT_Handler()の参照の前にの定義を置くか、そのSIGALRM_Handler()前に宣言を追加する必要があります。

static void SIGQUIT_Handler(int iSig);

どちらでも機能しますが、どちらか一方が必要です。なんで?あなたが書くとき:

signal(SIGQUIT, SIGQUIT_Handler);

2 番目の引数は関数へのポインターである必要がありますが、使用される前に宣言されているため、コンパイラーは名前が関数へのポインターを表すことを認識している必要があります。現状では、名前SIGQUIT_Handlerは宣言または定義されていないため、コンパイラはそれが何であるかを知りません。

于 2013-08-28T03:02:07.660 に答える