信号処理 シグナルハンドラは、signal(2) または sigaction(2) システムコールを使用してインストールできます。特定のシグナルに対してシグナルハンドラがインストールされていない場合は、デフォルトのハンドラが使用されます。それ以外の場合は、シグナルがインターセプトされ、シグナルハンドラが呼び出されます。プロセスは、ハンドラを作成せずに、2 つのデフォルトの動作を指定することもできます。シグナルを無視する ( SIG_IGN ) およびデフォルトのシグナルハンドラを使用する ( SIG_DFL ) です。インターセプトして処理できないシグナルが 2 つあります。SIGKILLとSIGSTOP です 。
リスク シグナル処理は競合状態 の影響を受けやすい。シグナルは非同期であるため、シグナル処理ルーチンの実行中に、別のシグナル(同じタイプのシグナルであっても)がプロセスに送信される可能性がある。
sigprocmask (2) 関数を使用すると、シグナルの配信をブロックおよびブロック解除できます。ブロックされたシグナルは、ブロックが解除されるまでプロセスに配信されません。無視できないシグナル ( SIGKILL およびSIGSTOP ) はブロックできません。
シグナルは進行中のシステムコールを中断させる可能性があり、アプリケーションは非透過的な再起動 を管理する必要が生じる。
シグナルハンドラは、 errno の 変更、シグナルマスクの変更、シグナル処理の変更、その他のグローバルなプロセス 属性の変更など、望ましくない副作用を引き起こさないように記述する必要があります。シグナルハンドラ内で、malloc やprintf などの再入 不可能な関数を使用することも安全ではありません。特に、POSIX 仕様と Linux の man ページsignal (7) では、シグナル関数から直接的または間接的に呼び出されるすべてのシステム関数が 非同期シグナル セーフであることを要求しています。[ 6 ] [ 7 ] signal -safety(7) man ページには、このような非同期シグナルセーフなシステム関数 (実際には システムコール )のリストが記載されています。そうでない場合は、未定義の動作 となります。[ 8 ] シグナルハンドラ内で何らかの変数を設定し、それを別の場所でテストすることが推奨されます。 [ 9 ] volatile sig_atomic_t
シグナル ハンドラは、代わりにシグナルをキュー に入れてすぐに戻ることができます。メイン スレッドは、イベント ループなどでシグナルがキューから取り出されるまで「中断されずに」続行されます。ここで「中断されずに」とは、 ブロック する操作が途中で戻り、再開する必要がある ことを意味します(前述のとおり)。シグナルは、非同期性の問題が再導入されるため、ワーカー プール ではなく、メイン スレッドのキューから処理する必要があります。ただし、キューの管理は、非同期シグナルに対して安全な方法では不可能です。なぜなら、そのような変数への単一の読み取りと書き込みのみがアトミックであることが保証されており、キューに必要なインクリメントや(フェッチと)デクリメントは保証されていないからです。したがって、処理されるまで、sig_atomic_tハンドラごとに安全にキューに入れることができるシグナルは実質的に 1 つだけです。sig_atomic_t
ハードウェア例外との関係 プロセスの実行によってハードウェア例外 が発生する場合があります。 たとえば、プロセスがゼロ除算を試みたり、ページフォルト が発生したりした場合などです。
Unix系 オペレーティングシステムでは、このイベントが発生すると、プロセッサのコンテキストが自動的に変更され、 カーネル 例外ハンドラの 実行が開始されます。ページフォルト などの例外が発生した場合、カーネルはイベントを完全に処理し、プロセスの実行を再開するのに十分な情報を持っています。
しかし、その他の例外については、カーネルはそれらを適切に処理することができず、例外処理を障害が発生したプロセスに委ねる必要があります。この委ねはシグナルメカニズムによって実現され、カーネルは現在の例外に対応するシグナルをプロセスに送信します。例えば、プロセスがx86 CPU 上で整数除算(ゼロ除算)を試みると、除算エラー例外が発生し、カーネルは SIGFPE シグナルをプロセスに送信します。
同様に、プロセスが仮想アドレス空間 外のメモリ アドレスにアクセスしようとした場合、カーネルはSIGSEGV (セグメンテーション違反 シグナル) を介してプロセスにこの違反を通知します。例外の種類はアーキテクチャによって異なるため、シグナル名と例外の正確な対応関係は明らかに CPU に依存します。
POSIXシグナル 以下のリストは、Single Unix Specification Version 5で規定されているシグナルをまとめたものです。すべてのシグナルは、ヘッダーファイル内でマクロ定数として定義されています<signal.h>。マクロ定数の名前は、「SIG 」という接頭辞 に続いて、シグナルの略称が続きます。
プロセスは、受信したPOSIXシグナルをどのように処理するか を定義できます。プロセスがシグナルの動作を定義していない場合、そのシグナルのデフォルトハンドラが使用されます。以下の表は、 FreeBSD 、OpenBSD 、Linux などのPOSIX準拠のUNIXシステムにおけるデフォルトの動作の一部を示しています。
携帯番号: ほとんどの信号の場合、対応する信号番号は実装定義です。この列には、POSIX 標準で指定されている番号が一覧表示されます。[ 10 ] 手順の説明: 終了 – プロセスの異常終了。プロセスは、指定されたシグナルによって異常終了を示すステータスを除き、すべての結果を伴って終了します。 _exit()wait()waitpid()終了(コアダンプ) – プロセスの異常終了。さらに、コアファイルの作成など、実装定義の異常終了処理が発生する場合があります。 無視 – 信号を無視します。 停止 – プロセスを停止(または一時停止)します。 続行 – プロセスが停止している場合は続行します。そうでない場合は、信号を無視します。 SIGABRT とシギオット SIGABRTシグナルは、プロセスに中止 、つまり終了を指示するために送信されます。このシグナルは通常、 プロセス自身がC標準ライブラリ の関数を呼び出す際に開始されますが、他のシグナルと同様に外部からプロセスに送信することもできます。abort() SIGIOTは 、CPUが明示的な「トラップ」命令(定義済みの関数がない)を実行したか、または未実装の命令(エミュレーションが利用できない場合)を実行したことを示します。 注:「入出力トラップ」は、CPUの「トラップ」命令全般を指す不適切な名称です。この用語は、主にI/O機能を実装するために初期に使用された命令を反映したものですが、これらの命令は必ずしもデバイスのI/Oに限定されるものではなく、仮想ホストと実ホスト間の通信など、他の目的にも使用できます。 SIGIOT とSIGABRTは 通常同じ信号であり、その信号を受信すると、上記のいずれかの状態を示している可能性があります。SIGALRM 、SIGVTALRM とSIGPROF SIGALRM 、SIGVTALRM 、SIGPROFシグナルは 、 対応する時間制限に達したときにプロセスに送信されます。プロセスは、またはを呼び出すことによってこれらの時間制限を設定します。SIGALRMの 時間制限は実時間またはクロック時間に基づきます。SIGVTALRMは プロセスが使用する CPU 時間に基づきます。SIGPROFはプロセスと、そのプロセスに代わってシステムが使用する CPU 時間 ( プロファイリング タイマー として知られています) に基づきます。一部のシステムでは、SIGALRM は 関数の実装によって内部的に使用される場合があります。alarmsetitimersleep シグバス SIGBUS信号は、プロセスが バスエラーを 引き起こした際に送信されます。この信号が送信される原因となる状況としては、例えば、メモリへのアクセスアライメントの誤りや、存在しない物理アドレスなどが挙げられます。 シグナルド SIGCHLDシグナルは、 子プロセスが 終了した とき、停止したとき、または停止後に再開したときにプロセスに送信されます。このシグナルの一般的な用途の1つは、システムコールを明示的に呼び出すことなく、子プロセスの終了後に子プロセスが使用したリソースをオペレーティングシステムにクリーンアップさせることです。wait シグナルコント SIGCONTシグナルは 、 SIGSTOP またはSIGTSTP シグナルによって一時停止されたプロセスを再開 (再起動)するようにオペレーティングシステムに指示します。このシグナルの重要な用途の1つは、Unixシェル におけるジョブ制御 です。 SIGFPE SIGFPEシグナルは 、浮動小数点演算または整数演算ハードウェアで例外的な(必ずしもエラーとは限らない)状態が検出された場合にプロセスに送信されます。これには、ゼロ除算 、浮動小数点アンダーフローまたはオーバーフロー、整数オーバーフロー 、無効な演算、または不正確な計算などが含まれます。動作はハードウェアによって異なる場合があります。 シグアップ SIGHUPシグナル は、制御端末が閉じられたときにプロセスに送信されます。元々は、シリアル回線 の切断 (ハングアップ ) をプロセスに通知するために設計されました。現代のシステムでは、このシグナルは通常、制御擬似端末または仮想端末 が閉じられたことを意味します。[ 11 ] 制御端末を持たない多くのデーモンは 、このシグナルを受信すると、終了する代わりに設定ファイルを再読み込みし、ログファイルをフラッシュ/再オープンする要求として解釈します。[ 12 ] nohup は 、コマンドにシグナルを無視させるコマンドです。 シギル SIGILLシグナルは、プロセス が不正な 、形式が不正な、未知の、または特権的な命令 を実行しようとしたときに、そのプロセスに送信されます。 SIGINT SIGINTシグナルは、ユーザーがプロセスを中断したいときに 、制御端末からプロセスに送信されます。これは通常 + を押すことで開始されますが、一部のシステムでは「delete 」文字または「break 」キーを使用できます。[ 13 ] Ctrl C シグキル SIGKILL シグナルは、プロセスを即座に終了させる( killする )ためにプロセスに送信されます。SIGTERMおよびSIGINT と は異なり、このシグナルは捕捉または無視することはできず、受信側のプロセスはこのシグナルを受信してもクリーンアップ処理を実行できません。以下の例外が適用されます。 ゾンビプロセスは 既に終了しており、親プロセスがそれらを回収するのを待っているため、強制終了することはできません。ブロック状態にあるプロセスは、再び起動するまで終了しません。 initプロセスは特別です。処理したくないシグナルは受け取らないため、SIGKILL を無視できます。[ 14 ] このルールの例外は、Linux で init が ptraced されている間 です。 [ 15 ] [ 16 ] 中断不可能なスリープ状態のプロセスは、 SIGKILLシグナル が送信されても終了せず(リソースを解放しない)、一時的なソフトウェアの問題を解決するためにUNIXシステムを再起動する必要がある数少ないケースの1つです。 SIGKILL は、ほとんどのシステム シャットダウン手順において、プロセスが SIGTERM に応答して自発的に終了しない場合の最終手段として使用されます。コンピュータのシャットダウン手順を高速化するために、Mac OS X 10.6 (別名Snow Leopard ) は、自身を「クリーン」とマークしたアプリケーションに SIGKILL を 送信し、おそらく悪影響なくシャットダウン時間を短縮します。[ 17 ] このコマンドは、例えば Linux で実行されると、同様の、しかし危険な効果を持ちます。プログラムが保存されていないデータを保存できないようにします。他のオプションもありますが、オプションがない場合は、より安全な SIGTERM シグナルを使用します。killall -9シグナルパイプ SIGPIPEシグナルは、プロセスが パイプのもう一方の端にプロセスが接続されていない状態でパイプ に書き込みを試みた際に、そのプロセスに送信されます。 SIGPOLL SIGPOLLシグナルは、明示的に監視されているファイルディスクリプタでイベントが発生したときに送信されます。[ 18 ] これを使用すると、 カーネルが呼び出し元の代わりにディスクリプタをポーリングするため 、非同期 I/O リクエストが効果的に作成されます。これは、アクティブポーリング の代替手段となります。 SIGRTMIN をSIGRTMAX SIGRTMINからSIGRTMAXまでの信号は 、 ユーザー定義の目的で使用することを想定しています。これらはリアルタイム 信号です。 SIGQUIT SIGQUITシグナルは、ユーザーがプロセスの 終了 とコアダンプの 実行を要求したときに、制御端末からプロセスに送信されます。 SIGSEGV SIGSEGVシグナルは、 プロセスが無効な仮想メモリ参照、つまり セグメンテーション 違反を 行ったときにプロセスに送信されます。[ 19 ] 信号停止 SIGSTOPシグナルは、 オペレーティングシステムに対し、後で再開するためにプロセスを停止するよう指示する。 SIGSYS SIGSYS シグナルは、プロセスがシステムコール に不正な引数を渡したときに送信されます。実際には、アプリケーションはライブラリ ( libc など) にシステムコールを代行させるため、この種のシグナルはめったに発生しません。SIGSYSは 、制限するように構成されたLinux Seccompセキュリティルールに違反するアプリケーションによって受信される可能性があります。SIGSYS は 、外部システムコールをエミュレートするためにも使用できます。たとえば、Linux 上で Windows システムコールをエミュレートできます。[ 20 ] SIGTERM SIGTERMシグナルは、プロセスの終了を 要求するためにプロセスに送信されます。SIGKILLシグナルとは異なり、プロセスはこのシグナルを捕捉して解釈することも、無視することもできます。これにより 、 プロセスはリソースを解放し、必要に応じて状態を保存して、正常な終了処理を実行できます。SIGINTは SIGTERM とほぼ同じです。 SIGTSTP SIGTSTPシグナルは、制御端末 からプロセスに送信され、プロセスに 停止 (端末 停止)を要求します。これは通常、 ユーザーが+キー を押すことで開始されます。SIGSTOPとは異なり、プロセスはこのシグナル の シグナルハンドラを登録することも、無視することもできます。Ctrl Z シグティン とシグトウ SIGTTINおよびSIGTTOUシグナルは 、 プロセスがバックグラウンドで tty からそれぞれ読み書き しようとした ときに送信されます。通常、これらのシグナルはジョブ制御 下のプロセスのみが受信します。デーモンは 制御端末を持たないため、これらのシグナルを受信することはありません。 SIGTRAP SIGTRAPシグナルは、例外(または トラップ )が発生したときにプロセスに送信されます。例外とは、デバッガが 通知を要求した状態、 例えば特定の関数が実行されたときや、特定の 変数の 値が変更されたときなどです。 シグルグ SIGURGシグナルは、 ソケット に読み取り可能な緊急 データまたは帯域外データ が存在する場合に、プロセスに送信されます。 SIGUSR1 とSIGUSR2 SIGUSR1およびSIGUSR2シグナルは 、 ユーザー定義の条件 を示すためにプロセスに送信されます。 SIGXCPU SIGXCPUシグナルは、プロセス が特定のあらかじめ設定されたユーザー設定値を超える 期間CPU を使用した場合に、そのプロセスに送信されます。 [ 21 ] SIGXCPU シグナルが到着すると、受信側のプロセスは、オペレーティングシステムがSIGKILL シグナルを使用して終了させる前に、中間結果をすばやく保存して正常に終了する機会を得ます。 SIGXFSZ SIGXFSZシグナルは、プロセスが 最大許容サイズ を超える ファイル を作成したときに送信されます。 シグウィンチ SIGWINCH信号は、制御端末のサイズが変更されたとき( ウィンドウ が変更 されたとき)にプロセスに送信されます。[ 22 ]
その他の信号 以下のシグナルはPOSIX 規格には規定されていません。しかし、様々なシステムで時折使用されています。
シゲムト SIGEMT信号は、エミュレータ トラップ が発生したときにプロセスに送信されます。通常、エミュレータとは他 の プログラムを実行するソフトウェアを指しますが、この場合はプログラムがスーパーバイザ呼び出し 命令を実行したことを意味します( DEC PDP-11 シリーズのコンピュータでは、EMT命令がこの目的のために使用されていました)。 SIGINFO SIGINFOシグナルは、 制御端末からステータス(情報 )要求を受信したときにプロセスに送信されます。 SIGPWR SIGPWR信号は、システムが 停電を 経験した際にプロセスに送信されます。 シグロスト SIGLOSTシグナルは、ファイルロックが 失われた ときにプロセスに送信されます。 シグストクフト SIGSTKFLTシグナルは、コプロセッサがスタック 障害 (スタックが空のときにポップしたり、スタックがいっぱいのときにプッシュしたりする)を経験したときにプロセスに送信されます。[ 23 ] これ は Linux で定義されていますが、Linux では使用されていません。Linux では、x87 コプロセッサのスタック障害が発生した場合、代わりにSIGFPE が生成されます。[ 24 ] シグナル使用済み SIGUNUSEDシグナルは、 未使用の システムコール番号を持つシステムコールが行われたときにプロセスに送信されます。ほとんどのアーキテクチャではSIGSYS と同義です。[ 23 ] SIGCLD SIGCLDシグナルは SIGCHLD と同義である。[ 23 ]
参考文献 ↑ McIlroy, MD (1987). A Research Unix reader: annotated excerpts from the Programmer's Manual, 1971–1986 (PDF) (Technical report). CSTR. Bell Labs. 139.↑ ガリアルディ、ピエトロ。 「ベル研究所の Plan 9 における C プログラミング」 。doc.cat -v.org。2022 年 1 月 22 日 取得 。 ↑ 「終了シグナル」 。GNU Cライブラリ) 。 ↑ 「ジョブ制御信号」 。GNU Cライブラリ 。 ↑ 「その他のシグナル」 。GNU Cライブラリ 。 ↑ 「The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition: System Interfaces Chapter 2」 。pubs.opengroup.org 。 2020 年 12月20日 取得 。 ↑ "signal(7) - Linux マニュアルページ" . man7.org . 2020年 12月20日 取得 . ↑ "signal-safety(7) - Linux マニュアルページ" . man7.org . 2020年 12月20日 取得 . ↑ "The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition: <signal.h>" . pubs.opengroup.org . 2020年 12月20日 取得 . ↑ 「IEEE Std 1003.1-2017 - kill」 。IEEE、Open Group。整数値と使用される sig 値の対応関係を以下のリストに示します。以下にリストされている以外の signal_number を指定した場合の影響は 未定義です。 ↑ Michael Kerrisk (2009年7月25日). "signal(7)" . Linux Programmer's Manual (バージョン3.22) . The Linux Kernel Archives . 2009年 9月23日 取得 . ↑ "perlipc(1)" . Perl プログラマーズ リファレンス ガイド、バージョン 5.18 . perldoc.perl.org - Perl プログラミング言語の公式ドキュメント. 2013 年 9 月 21 日 取得 . ↑ 「SIGINTとSIGQUITの適切な取り扱い」 。 2012年 10月6日 取得 。 ↑ https://manpages.ubuntu.com/manpages/zesty/man2/kill.2.html 2018年1月28日にWayback Machineの NOTESセクションに アーカイブされました ↑ "SIGKILL init process (PID 1)" 。 Stack Overflow 。 ↑ 「root権限でinitプロセスを強制終了できますか?」 . Unix & Linux Stack Exchange . ↑ 「Mac Dev Center: Mac OS X の新機能: Mac OS X v10.6」 。2009 年 8 月 28 日。2017 年 11 月 18 日 取得 。 ↑ 「ioctl - STREAM デバイスを制御する」 。POSIX システムコール仕様 。The Open Group。2015 年 6 月 19 日 に取得 。 ↑ 「セグメンテーション違反とは何ですか?」 . support.microfocus.com . 2018年 11月22日 取得 。 ↑ 「Syscall User Dispatch – Linux Kernel ドキュメント」 . kernel.org . 2021年 2月11日 取得 。 ↑ "getrlimit、setrlimit - 最大リソース消費量を制御する" . POSIX システムコール仕様 . The Open Group . 2009年 9月10日 取得 . ↑ Clausecker, Robert (2017年6月19日). "0001151: 端末ウィンドウサイズを取得/設定するための新しいシグナルSIGWINCHと関数tcsetsize()、tcgetsize()を導入" . Austin Group Defect Tracker . Austin Group . 2017年 10月12日 取得 . 承認済み 1 2 3 "signal(7) — Linux マニュアル ページ" . manpages.courier-mta.org . 2018 年 11 月 22 日 取得 . ↑ 「Linux 3.0 x86_64: SIGSTKFLT はいつ発生しますか?」 . Stack Overflow . Stevens, W. Richard (1992). 『UNIX®環境における高度なプログラミング』 。 マサチューセッツ州レディング:Addison Wesley。ISBN 0-201-56317-7 。「The ®Open Group Base Specifications Issue 8, IEEE Std 1003.1™-2024 Edition」。The Open Group 。 2025年 3月2日 取得 。
外部リンク Unixシグナルテーブル、アリ・アランジャウィ、ピッツバーグ大学 Man7.org シグナルマンページ Unixシグナルプログラミング入門 Wayback Machine にアーカイブされ たUnixシグナルプログラミング入門(2013年9月26日) Unixシグナルプログラミング入門(ブログ記事、2009年) バリス・シムセク著『 UNIXと信頼性の高いPOSIXシグナル』 (インターネットアーカイブ に保存) ヘニング・ブラウアー著『シグナル・ハンドラーズ』