2017-09-26 11 views
0

私はシグナルハンドラを2つの独立したプロセス、すなわち通知のためのライタとリーダのコンテキストで作業したいと考えています。ライタは、ライタからの第2の信号SIGUSR2を聞くまでループする第1の信号SIGUSR1をリーダに送る。 writer.cでCのネストされたシグナルハンドラ

reader.c

static volatile sig_atomic_t done_waiting; 

int handler1(int signal){ 
    done_waiting = 0; 
    while(!done_waiting){ 
      (void)fprintf(stdout, " reader waiting for sigusr2: done_waiting = %d\n", done_waiting); 
    } 
(void)fprintf(stdout, " reader received sigusr2 \n); 
} 

int handler2 (int signal){ 
     done_waiting = 1; 
} 

main(){ 
    signal(SIGUSR1, handler1); 
    signal(SIGUSR2, handler2); 
    sleep(5); // sleep till we start worker 
} 

、信号がIは、読者が最初のワーカー続い実行すると、プログラムはwhileループで終了

main(){ 
    kill(pid_reader, SIGUSR1); 
    sleep(5); 
    kill (pid_reader, SIGUSR2); 
} 

としてリーダに送信されます。そして、執筆者は、「あなたに属する一致するプロセスは見つかりませんでした」と印刷します。

ネスティングシグナルハンドラは許可されていますか?はいの場合は推奨されますか?また、ライターが準備ができていることを読者に知らせるための他の代替メカニズムがありますか?

+1

参照[ 'シグナルハンドラでのprintf()'使用して回避する方法?](http://stackoverflow.com/questions/16891019/how-で、Linux上でテスト済み基本的な情報のためにシグナル・ハンドラ/を使用してシグナル・ハンドラを使用しないようにする)。シグナルハンドラでできるだけ少なくする必要があります。シグナルハンドラでどの関数を呼び出すことができるか厳密に制限されています。また 'printf()'関数群はOK関数のリストにはありません(どちらも助けあれば 'strlen 'printf()'その他の理由があり、 'strlen()'の良い理由は分かりません)。 –

+1

シグナルハンドラを「入れ子にしている」わけではなく、ハンドラを異なるシグナル用に2つインストールしました。また、 'sigsuspend(2)'とそれに関連した呼び出しを見てください。これはシグナルを待つことができます( 'while'ループでここで待っています)。 – bnaecker

答えて

0

は多分信号実際にあなたが何を意味するのか、ネストされていない信号ハンドラを入れ子になっていますか?明確にするために、SIGUSR1のハンドラが実行されているときにSIGUSR2が受信された場合、どうなるでしょうか?私はそうだと思う。

私はあなたのコードをいくつかの変更を加えてテストし、読者プロセスのためのpidをライタープロセスに取得した。私はargsをmainに使った。

私が得た結果は次のとおりです。

  1. まずリーダーは、それが連続的にこれは、それがあることを示し、それはSIGUSR2
  2. 待つことSIGUSR2を受信すると、それは「読者がSIGUSR2を受信した」印刷

の書き込みを開始SIGUSR1を受信した後

  • 静かですネストされた信号を持つことが可能です。しかし私はそれが意図的なデザインとして推奨されているとは言いません。 コメントの中で述べたように、シグナルハンドラでできるだけ少なく、whileループでループしないでください。 また、コメントでも触れたように、シグナルコンテキストでどのような関数を呼び出すかは非常に注意してください。printf()は正常に動作しているように見えますが、問題ありません。

    は、古代のカーネル3.16とgcc 4.9

  • 関連する問題