回答:
「信号が多すぎる」問題は別として、信号は明示的に無視できます。からman 2 signal
:
If the signal signum is delivered to the process, then one of the
following happens:
* If the disposition is set to SIG_IGN, then the signal is ignored.
信号をブロックすることもできます。からman 7 signal
;
A signal may be blocked, which means that it will not be delivered
until it is later unblocked. Between the time when it is generated
and when it is delivered a signal is said to be pending.
シグナルのブロックされたセットと無視されたセットの両方が子プロセスによって継承されるため、アプリケーションの親プロセスがこれらのシグナルの1つを無視またはブロックした可能性があります。
プロセスが前のシグナルの処理を完了する前に複数のシグナルが配信されるとどうなりますか?それはOSに依存します。signal(2)
議論し、それを上記のリンクmanページ:
libc
に設定されたコンパイルフラグに依存しますが、BSDの動作を期待します。送信されたすべての信号が配信されるとは信じられません。たとえば、終了した子プロセスからのSIGCHLDの処理にプロセスに長い時間がかかる場合、LinuxカーネルはSIGCHLDを「結合」します。
あなたの質問の別の部分に答えるために、いくつかの異なるシグナルが間隔が短すぎて到着した場合、シグナルはカーネル内で「キュー」に入れられます。
を使用sigaction()
して、のsa_sigaction
メンバーでシグナルハンドラをsiginfo_t
設定しsa_mask
、siginfo_t
引数のメンバーを慎重に設定する必要があります。これは、少なくとも「非同期」信号のすべてをマスクすることを意味すると思います。Linuxのmanページによると、sigaction()
処理される信号もマスクされます。sa_flags
メンバーをSA_SIGINFOに設定する必要があると思いますが、この迷信がある理由を思い出せません。これにより、競合状態のないまま設定されたシグナルハンドラーと、他のほとんどのシグナルによって中断されないシグナルハンドラーがプロセスに提供されると思います。
シグナルハンドラー関数を非常に慎重に記述します。基本的には、グローバル変数を設定して、シグナルがキャッチされたことを示し、残りのプロセスにそのシグナルに必要なアクションを処理させるだけです。信号はそのようにして最短時間だけマスクされます。
また、信号処理コードを非常に徹底的にテストする必要があります。小さなテストプロセスに入れて、SIGUSR1およびSIGUSR2信号をできるだけ多く送信します。2つまたは3つの専用信号送信プログラムから送信される可能性があります。コードがSIGUSR1とSIGUSR2を迅速かつ正しく処理できることを確認したら、他のいくつかの信号も混ぜます。難しいデバッグに備える。
Linuxを使用していてLinuxのみを使用している場合は、を使用signalfd()
して、select()
これらの信号を受信するためにポーリングまたはポーリングできるファイル記述子を作成することを検討する場合があります。を使用signalfd()
すると、デバッグが容易になります。
シグナルは、プロセスが正常に呼び出された場合に配信されることが保証されています kill
、ターゲットは信号を受信します。これは非同期です。送信者は、信号がいつ受信または処理されたかを知る方法がありません。ただし、これは信号が配信されることを保証するものではありません。ターゲットは、信号を処理する前に停止する可能性があります。ターゲットが配信時にシグナルを無視している場合、シグナルは効果がありません。ターゲットが処理する前に同じシグナル番号の複数のインスタンスを受信する場合、シグナルはマージされる可能性があります(通常はマージされます)。同じシグナルをプロセスに2回送信した場合、プロセスがシグナルを受信するかどうかがわかりません。一回か二回。シグナルは、ほとんどの場合、プロセスを強制終了するように設計されているか、プロセスに注意を向けさせる方法として設計されています。これらは、通信自体のために設計されていません。
信頼できる配信が必要な場合は、別の通信メカニズムが必要です。プロセス間の主な通信メカニズムは2つあります。パイプは単一方向通信を可能にします。ソケットは、双方向通信と同じサーバーに複数の接続を可能にします。ターゲットが送信する通知と同じ数の通知を処理する必要がある場合は、パイプを介してバイトを送信します。
ブロックされている間に複数のシグナルが配信された場合、カーネルは標準シグナルを自由に合体できます。一方、リアルタイム信号には同様の障害はありません。
以下からの信号(7)のマニュアルページ:
リアルタイム信号は、以下によって区別されます。
- リアルタイム信号の複数のインスタンスをキューに入れることができます。対照的に、その信号が現在ブロックされている間に標準信号の複数のインスタンスが配信される場合、1つのインスタンスのみがキューに入れられます。
SIGRTMINからSIGRTMAXの範囲の数値の信号を使用してみてください。
ulimit -i
Ubuntu 18.04では、この値は63432と表示されます。
signal(2)
は、sigaction(2)
代わりにを使用してこの混乱を回避することを強調しています。