「シグナルが多すぎる」問題は別として、シグナルは明示的に無視できます。 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)
上記のリンクのマンページで説明しています:
- システム V は、信号処理をデフォルトにリセットします。さらに悪いことに、複数のシグナルを迅速に配信すると、再帰的 (?) 呼び出しが発生します。
- BSD は、ハンドラーが完了するまでシグナルを自動的にブロックします。
- Linux では、これは GNU
libc
に設定されたコンパイル フラグに依存します。 、しかし、BSD の動作を期待します。
送信されたすべてのシグナルが配信されるとは信じられません。たとえば、プロセスが終了した子プロセスからの SIGCHLD の処理に時間がかかる場合、Linux カーネルは SIGCHLD を「結合」します。
質問の別の部分に答えると、間隔が短すぎる間に多数の異なるシグナルが到着すると、シグナルはカーネル内で「キューに入れられます」。
sigaction()
を使用する必要があります sa_sigaction
でシグナルハンドラを設定する siginfo_t
のメンバー 、 sa_mask
を設定 siginfo_t
のメンバー 議論は慎重に。これは、少なくとも「非同期」シグナルをすべてマスキングすることを意味すると思います。 Linux sigaction()
のマニュアルページによると 、処理中の信号もマスクします。 sa_flags
を設定する必要があると思います SA_SIGINFO のメンバーですが、なぜこの迷信があるのか思い出せません。これにより、競合状態が発生せずに設定されたままになり、他のほとんどのシグナルによって中断されないシグナルハンドラーがプロセスにもたらされると思います.
シグナルハンドラ関数は、非常に慎重に記述してください。基本的には、シグナルがキャッチされたことを示すグローバル変数を設定し、プロセスの残りの部分でそのシグナルの目的のアクションを処理するだけです。そうすれば、シグナルは最小限の時間だけマスクされます。
また、シグナル処理コードを徹底的にテストする必要があります。それを小さなテストプロセスに入れて、おそらく2つまたは3つの特別な目的のシグナル送信プログラムから、できるだけ多くのSIGUSR1およびSIGUSR2シグナルを送信します。コードが SIGUSR1 と SIGUSR2 を迅速かつ正確に処理できることを確信したら、他のいくつかのシグナルも混ぜます。困難なデバッグに備えてください。
Linux を使用していて Linux のみを使用している場合は、signalfd()
を使用することを検討してください。 select()
できるファイル記述子を作成する またはそれらの信号を受信するためにポーリングします。 signalfd()
の使用 デバッグが容易になるかもしれません。
プロセスが kill
の呼び出しに成功した場合、シグナルの配信が保証されます。 、その後、ターゲットは信号を受信します。これは非同期です。送信者は、信号がいつ受信または処理されたかを知る方法がありません。ただし、これは信号が配信されることを保証するものではありません。ターゲットは、信号を処理する前に死亡する可能性があります。ターゲットが配信時に信号を無視している場合、信号は何の効果もありません。ターゲットがそれらを処理する前に同じシグナル番号の複数のインスタンスを受信した場合、シグナルはマージされる可能性があります (通常はマージされます)。プロセスに同じシグナルを 2 回送信すると、プロセスがシグナルを受信するかどうかを知ることができません。一回か二回。シグナルは主にプロセスを強制終了するか、プロセスに注意を向けさせる方法として設計されており、そのような通信用には設計されていません。
信頼性の高い配信が必要な場合は、別の通信メカニズムが必要です。プロセス間の主な通信メカニズムは 2 つあります。パイプは単方向通信を可能にします。ソケットは、双方向通信と同じサーバーへの複数接続を可能にします。送信した数の通知をターゲットで処理する必要がある場合は、パイプ経由でバイトを送信します。