2011-12-28 9 views
2

私は、次のプログラムに複数のその後のHangup信号を送信する場合、それらの2つだけが処理されると、残りは無視されます。2つ以上の連続した信号を捕捉するには?

#include <stdio.h> 
#include <unistd.h> 
#include <signal.h> 

int id; 
void handler(int s) 
{ 
    id++; 
    int i; 
    for(i=0; i<3; i++) 
    { 
     printf("Sig %d\n", id); 
     sleep(2); 
    } 
} 

int main() 
{ 
    int i; 
    signal(SIGHUP, handler); 
    for(i=0; ; i++) 
    { 
     printf("%d\n", i); 
     sleep(1); 
    } 
    return 0; 
} 

私はプロセスにシグナルを送信するには、次のコマンドを使用します。

kill -l {#process} 

私は3回連続して上記のコマンドを実行した場合、第三信号は、以下の出力のように無視されます。

0 
1 
2 
3 
4 
5 
6 
7 
Sig 1 
Sig 1 
Sig 1 
Sig 2 
Sig 2 
Sig 2 
8 
9 
10 
11 
12 

第3の信号も捕まえる方法はありますか?

+2

シグナルハンドラ内でスリープ状態になることは疑わしいです。それはそこになければなりませんか? – wallyk

+0

@wallykマニュアルページによると、POSIX.1-2004では、シグナルハンドラ内で安全にsleepする必要があります。 –

+0

通常のシグナルはキューに入れられません。 – nos

答えて

2

通常、標準信号ではできません。 Unixカーネルは、通常、保留中のシグナルを1つだけキューに入れます。 Sig1ハンドラでプロセススリープ中にSig2とSig3が送信されると、それらはマージされます。

シグナルハンドラをセットアップしてSA_NODEFERフラグを供給するためにsigaction(2)を使用できます。それはシグナルハンドラ中に新しいシグナルを送ることを可能にするでしょう。ハンドラが再実行されていることを確認してください。エラーが発生しやすいソリューションです。

また、「リアルタイム信号」と呼ばれるPOSIX.1b(POSIX.1-2001)拡張もあります。そのようなシグナルは複数回キューに入れることができますが、SIGHUPはそれらのシグナルの1つではありません。 Linux上のsignal(7)では、リアルタイム信号には33(SIGRTMIN)〜64(SIGRTMAX)の番号が付けられています。

1

Linuxでは、保留中の信号は1ビットで表されます。つまり、ハンドラがすでに実行されている間に複数のシグナルが生成された場合、それはもう一度呼び出されます。

+0

自分のlinuxに 'ulimit -a'と入力すると' pending signals'にデフォルト値16383があることがわかります。 'getrlimit'とリソース名' RLIMIT_SIGPENDING'(これもやはり16383です)でテストしました。だから、Linuxがこのビット数の信号を1ビットで処理する方法は? – saeedn

+0

@saeednこれは、プロセスごとにユーザーごとに保留されるシグナルの合計数(実際には「実際のユーザーID」あたり)です。 1つの信号に対して、プロセスごとに、各タイプの1つの信号のみが保留されることがあります。 –

関連する問題