60

Linux で非同期シグナル ハンドラーの実行がどのように機能するかを正確に知りたいです。まず、どのスレッドがシグナル ハンドラを実行しているかがわかりません。次に、スレッドにシグナル ハンドラを実行させるための手順を知りたいです。

最初の問題について、一見相反するように見える 2 つの異なる説明を読みました。

  1. The Linux Kernel, by Andries Brouwer, §5.2「シグナルの受信」には次のように記載されています。

    シグナルが到着すると、プロセスが中断され、現在のレジスタが保存され、シグナル ハンドラが呼び出されます。シグナル ハンドラーが戻ると、中断されたアクティビティが続行されます。

  2. StackOverflowの質問「マルチスレッド プログラムでの非同期シグナルの処理」により、Linux の動作はSCO Unix の動作に似ていると思います。

    シグナルがプロセスに配信されるとき、シグナルがキャッチされている場合は、次の条件のいずれかを満たすスレッドの 1 つだけによって処理されます。

    1. キャッチされたシグナルのタイプが引数に含まれている sigwait (2) システムコールでブロックたスレッド。

    2. キャッチされたシグナルのタイプがシグナルマスクに含まれていないスレッド。

    その他の考慮事項:

    • sigwait (2)でブロックされたスレッドは、シグナル タイプをブロックしていないスレッドよりも優先されます。
    • 複数のスレッドがこれらの要件を満たす場合 (おそらく 2 つのスレッドがsigwait (2)を呼び出している場合)、そのうちの 1 つが選択されます。この選択は、アプリケーション プログラムでは予測できません。
    • 適切なスレッドがない場合、スレッドが適切になるまで、シグナルはプロセスレベルで「保留中」のままになります。

    また、Moshe Bar による「The Linux Signals Handling Model」には、 「非同期シグナルは、シグナルをブロックしていないことが判明した最初のスレッドに配信されます」と記載されています。 .

どちらが正しいですか?

2 つ目の問題として、選択したスレッドのスタックとレジスタの内容はどうなるでしょうか。シグナルハンドラーを実行するスレッドTが関数の実行中にあるとしdo_stuff()ます。スレッドTのスタックは、シグナル ハンドラを実行するために直接使用されますか (つまり、シグナル トランポリンのアドレスがTのスタックにプッシュされ、制御フローがシグナル ハンドラに移動します)。または、別のスタックが使用されていますか? それはどのように機能しますか?

4

2 に答える 2

26

これら 2 つの説明は、Linux ハッカーがスレッドとプロセスの違いについて混乱する傾向があるという事実を考慮すると、実際には矛盾していません。メモリー。:-)

そうは言っても、説明#2ははるかに詳細で、完全で、正しいです。

スタックとレジスタの内容に関しては、各スレッドは独自の代替シグナル処理スタックを登録でき、プロセスは代替シグナル処理スタックで配信されるシグナルをシグナルごとに選択できます。中断されたコンテキスト (レジスタ、シグナル マスクなど) はucontext_t、トランポリンのリターン アドレスと共に、スレッドの (おそらく代替の) スタック上の構造体に保存されます。フラグとともにインストールされたシグナル ハンドラーは、SA_SIGINFOこれを調べることができます。ucontext_t必要に応じて構造化しますが、それでできる移植可能な唯一のことは、保存されたシグナル マスクを調べる (場合によっては変更する) ことです。(変更が標準で許可されているかどうかはわかりませんが、シグナルハンドラーが中断されたコードのシグナルマスクをリターン時にアトミックに置き換えることができるため、非常に便利です。たとえば、シグナルをブロックしたままにして、再発しないようにすることができます.)

于 2011-08-04T22:28:17.203 に答える