カーネルは、プロセス 1 が「プロセス 2 が終了するのを待っている」ことをあまり気にしません (特に、プロセス 1 が現在の状態にある「理由」には関心がなく、単に何らかの状態にあることに関心があります。この場合、何らかのイベントを待っているカーネルでアイドリング)。典型的な1キャッチシグナルの場合、シグナル送信者は基本的に、シグナル受信者のプロセス/スレッド状態にいくつかのビットを設定し、適切な場合は、そのプロセス/スレッドの実行をスケジュールして、それらのビットを確認できるようにします。レシーバーが何らかのイベントを待っているカーネルでアイドル状態になっている場合、それは「実行スケジュール」のケースの 1 つです。(その他の一般的な状況としては、受信機が STOP 状態にあり、次の場合を除いて停止したままです。SIGCONT
信号; または、受信側がユーザー モードで実行されており、保留中のシグナルに気付くようにカーネル モードに移行するように設定されています。)
との両方SIGKILL
をSIGSTOP
キャッチまたは無視することはできないため、これらのハンドラーを提供することはできません。SIGTSTP
(通常、プロセスは、SIGTTIN
、またはを介して停止状態になります。SIGTTOU
これらはすべてキャッチまたは無視できます。)
システム コールがユーザー シグナル ハンドラが返された後に再起動するように設定されている場合 ( のSA_RESTART
フラグを介してsigaction()
)、これは操作の「リターン アドレス」を設定してsigreturn()
、実際にはシステム コールを再度実行することによって実現されます。つまり、プロセス 1 が にある場合、waitpid()
(プロセス 1 の観点から) 最初の の時点からwaitpid()
、キャッチされたシグナルの受信を経て、s
さらに待機するまでの一連の操作は次のようになります。
- システムコール:
waitpid()
- イベントを待って自分をスリープ状態にする
- 目覚めた:覚醒イベントをチェック
- イベントはシグナルであり、シグナルはキャッチされるため、次のようになります。
- 設定ごとに新しいシグナル マスクを
sigaction()
設定します( を参照sigaction()
) 。
- スタック上のプッシュ信号フレーム (
SA_ONSTACK
およびを参照sigaltstack()
)
- 「シグナルトランポリン」で入力するユーザーコード(プログラムカウンター)の設定
- ユーザー コードに戻る (トランポリンに)
(この時点で、プロセス 1 はユーザー モードに戻ります。SO を 9 から開始することはできないため、残りのステップには番号が付けられていません。:-) )
- ユーザー ハンドラー ルーチンを呼び出す (上で選択したスタック上にある)
- ユーザールーチンが戻ったとき
sigreturn()
、セットアップ時に保存されたフレームを使用してシステムコールを実行し、ユーザールーチンによって変更される可能性があります
(この時点で、プロセスはカーネル モードに入り、sigreturn()
システム コールを実行します)
- システムコール: :引数
sigreturn()
で指定されたシグナルマスクを設定sigreturn()
sigreturn()
引数で指定されたように、スタック ポインターとプログラム カウンターを含むその他のレジスターを設定します。
- ユーザーコードに戻る
(プログラムはユーザーモードに戻り、レジスタは に入るように設定されていますwaitpid
)
- システムコール:
waitpid()
この時点で、プロセスはキャッチされたシグナルを受信する前と同じ状態に戻ります。つまりwaitpid
、イベントを待機してスリープ状態になります (ステップ 2)。目覚めると (ステップ 3)、待っていたイベントが発生し (例えば、処理中のプロセスwaitpid()
が完了)、正常に戻るか、別のキャッチされたシグナルが発生し、このシーケンスを繰り返す必要があるか、または処理中です。殺され、クリーンアップする必要があります。
このシーケンスは、一部のシステム コール (いくつかの - のread()
ようなシステム コールなど) が、シグナルによって中断された場合に「早期に戻る」理由です: カーネルへの「最初の」エントリとシグナル ハンドラが終了するまでの間に、元に戻せない何かを実行しました。実行されます。この場合、ステップ 6 でプッシュされたシグナル フレームには、システム コール全体を再起動させるプログラム カウンタ値が含まれていてはなりません。もしそうなら、プロセスがスリープ状態になる前に行われた元に戻せない作業は失われます。そのため、代わりに、システムコールの成功を検出した命令に戻るように設定され、レジスタ値はショートread()
カウントなどを返すように設定されます。
システムコールが再起動しないSA_RESTART
ように設定されている ( が設定されていない) 場合は、手順 6 でプッシュされる信号フレームも異なります。システム コールを実行する命令に戻る代わりに、失敗したシステム コールを検出した命令に戻り、レジスタ値がEINTR
エラーを示すように設定されます。
(常にではありませんが、多くの場合、これらは同じ命令です。たとえば、成功/失敗をテストするための条件分岐です。元の SPARC ポートでは、ほとんどの場合、それらを別の命令にしました。リーフ ルーチン%o6+8
は、レジスタまたはスタックなしで戻るため、成功したリターンはリーフ ルーチンのリターン アドレスに戻る必要があることを示すビットを設定しただけなので、ほとんどのシステム コールは「syscall 番号と ret-on-success フラグを に入れ%g1
、カーネルにトラップし、次にここに到達した場合、システムコールが失敗したに違いないため、エラー処理.")
1キューに入れられたシグナルに対して。