15 ( SIGTERM
) は、アプリケーションがそのように選択した場合、アプリケーションによってキャッチされて処理される可能性がありますが、おそらく現時点ではそうではありません
9 ( SIGKILL
) は明らかにどのアプリケーションでもキャッチできません。
ただし、通常、オペレーティング システムは、プロセスを終了させたシグナルを識別できるように終了ステータスを設定します。通常、exit(3) 関数 [したがって _exit(2) システム コール] への status パラメータの下位 8 ビットのみが、status
wait(2) によって親プロセス (外部スクリプトを実行するシェル) に返される値にコピーされます。あなたの例では)。そのため、OS が終了したプロセスに関する他の情報を入力するために使用する値に、sizeof(int)-1
バイト単位のスペースが残ります。status
通常、wait(2) のマニュアル ページには、待機ステータスを解釈する方法が記述されているため、プロセスが終了した場合に、プロセスが _exit(2) に渡したステータスからプロセス終了に関する追加情報を分割します。
残念ながら、この追加情報をスクリプトで利用できるようにするかどうかは、スクリプトを実行するシェルがそれを処理する方法によって異なります。
解釈方法の詳細については、最初にシェルのマニュアル ページを確認してください$?
。
シェルがstatus
int
値全体をスクリプトで (変数内で) 逐語的に使用$?
できるようにすると、値を解析して、プログラムが終了した方法と理由を判別できます。ほとんどのシェルはこれを完全に行っているようには見えません (そして、さまざまな理由で、少なくとも標準への準拠である可能性があります) が、少なくともクエリを解決できるようにするのに十分なほどのことを行っています (そして、POSIX である必要があります)。互換性)。
ここでは、たとえば、Mac OS X で KSH の AT&T バージョンを実行しています。私の ksh(1) マニュアル ページには、プログラムが正常に終了した場合の終了ステータスは 0-255 であると書かれています (値はおそらく渡されたものです)。 _exit(2)) および 256+signum (プロセスがシグナル ("signum" の番号) によって終了された場合)。Linux についてはわかりませんが、OS X では、bash は Ksh とは異なる終了ステータスを返します (bash は 8 番目のビットを使用してシグナルを表すため、有効な終了値として 0-127 のみを許可します)。(_exit(2) の 8 つの下位ビットが使用可能であるという wait(2) の主張と、シェルによる待機ステータスの$?
7 ビットのみを保持します。図に行く!Ksh の動作は POSIX に違反していますが、厳密に互換性のあるシェルでは、プロセスが _exit(2) に 128 ~ 255 の値を渡していることと、シグナルによって終了したことを区別できない可能性があるため、より安全です。)
とにかく、cat
プロセスを開始SIGQUIT
し、端末から送信します (^ を押して) (端末のキーボードからSIGQUIT
送信する簡単な方法がないため、使用します)。SIGTERM
22:01 [2389] $ cat
^\Quit(coredump)
ksh: exit code: 259
EXIT
( $? がゼロでない場合に $? を出力するように定義されたシェルトラップがあるので、上記にも表示されます)
22:01 [2390] $ echo $?
259
(259 は、wait(2) によってシェルに返されるステータスを表す整数値です)
22:02 [2391] $ bc
obase=16
259
103
^D22:03 [2392] $
(259 には 16 進値 0x0103 があることを確認してください。0x0100 は 256 10 進数であることに注意してください)
22:03 [2392] $ signo SIGQUIT
#define SIGQUIT 3 /* quit */
signo
(ヘッダーを検索してシンボリック シグナル名を表す番号を見つけるというシェル エイリアスがあります。ここで、ステータス値の 0x03 が と同じ番号であることを確認してくださいSIGQUIT
。)
wait(2) システム コールと関連するマクロをさらに調べると<sys/wait.h>
、何が起こっているのかをもう少し理解できるようになります。
C では、待機ステータスをデコードするための基本的なロジックは、次のマクロを使用します<sys/wait.h>
。
if (!WIFEXITED(status)) {
if (WIFSIGNALED(status)) {
termsig = WTERMSIG(status);
} else if (WIFSTOPPED(status)) {
stopsig = WSTOPSIG(status);
}
} else {
exit_value = WEXITSTATUS(status));
}
それが役立つことを願っています!