Ctrlc完了するまでに長い時間がかかっているプロセスを停止しようとして、シェルを 2 回実行しました。
^C
2回繰り返しましたが、プロセスはそのまま続行されました。
Ctrlc通常どおりにプロセスを終了しなかったのはなぜですか?
答え1
プロセスでは以下を選択できます。
- 通常、押すと送信される SIGINT シグナルを無視しますCtrl-C(シェル内の場合など
trap '' INT
)。または、終了しないことを決定する (または適切なタイミングで終了できない) 独自のハンドラーを用意します。 - 端末デバイスに、フォアグラウンドジョブに SIGINT が送信される原因となる文字が別の文字 (
stty int '^K'
シェル内の文字など)であることを伝えます。 - 端末デバイスに信号を送信しないように指示します (
stty -isig
シェル内の場合と同様)。
または、中断できないシステム コールの途中など、中断できない場合もあります。
Linux(比較的新しいカーネル)では、プロセスが無視されているか、または取り扱いSIGINTの出力を見て
$ kill -l INT
2
$ grep Sig "/proc/$pid/status"
SigQ: 0/63858
SigPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000002
SigCgt: 0000000000000000
SIGINT は 2 です。上記の SigIgn の 2 番目のビットは 1 であり、SIGINT は無視されることを意味します。
これを自動化するには、次の操作を実行します。
$ SIG=$(kill -l INT) perl -lane 'print $1 if $F[0] =~ /^Sig(...):/ &&
$F[1] & (1<<($ENV{SIG}-1))' < "/proc/$pid/status"
Ign
現在のintr
文字が何であるか、またはisig
特定の端末で有効になっているかどうかを確認するには:
$ stty -a < /dev/pts/0
[...] intr = ^C [...] isig
(上記の文字は、(通常、端末 (エミュレータ) が押したときに送信される文字intr
であり、入力信号は無効になっていません。^C
CTRL-C
$ stty -a < /dev/pts/1
[...] intr = ^K [...] -isig
(intr
文字は であり^K
、isig
では無効です/dev/pts/1
)。
完全を期すために、プロセスが SIGINT の受信を停止する方法が他に 2 つありますが、これは通常は見られない方法です。
するとCtrl+C、SIGINTシグナルがすべてのプロセスに送信されます。端末のフォアグラウンドプロセスグループプロセスをプロセスグループに配置するのは通常シェルです(シェルにマップされます)。仕事)を端末に伝え、前景1つ。
プロセスは次のことが可能になります。
プロセスグループを離れる。別のプロセスグループ(現在のプロセスグループ以外のプロセスグループ)に移動すると、前景1 の場合、SIGINT を受信しなくなりますCtrl-C(SIGTSTP、SIGQUIT などの他のキーボード関連のシグナルも受信しなくなります)。ただし、(バックグラウンド プロセスと同様に) 端末デバイスから読み取り (端末デバイスの設定によっては書き込みも可能) を試行すると、中断される可能性があります。
例:
perl -MPOSIX -e 'setpgid(0,getppid) or die "$!"; sleep 10'
は、 で割り込みできませんでしたCtrl-C。上記は、
perl
親プロセス ID と同じ ID を持つプロセス グループに参加しようとします。一般に、その ID を持つプロセス グループが存在するという保証はありません。ただし、ここでは、perl
対話型シェルのプロンプトでそのコマンドが単独で実行される場合、ppid はシェルのプロセスになり、シェルは通常、独自のプロセス グループで開始されます。コマンドがまだプロセス グループ リーダー (そのフォアグラウンド プロセス グループのリーダー) でない場合は、新しいプロセス グループを開始しても同じ効果が得られます。
例えば、シェルによっては、
$ ps -j >&2 | perl -MPOSIX -e 'setpgid(0,0) or die "$!"; sleep 10' PID PGID SID TTY TIME CMD 21435 21435 21435 pts/12 00:00:00 zsh 21441 21441 21435 pts/12 00:00:00 ps 21442 21441 21435 pts/12 00:00:00 perl
は同じ効果があります。
ps
と はperl
フォアグラウンド プロセス グループで開始されますが、ほとんどのシェルでは がps
そのグループのリーダーになります (上記の出力でわかるように、と のps
両方の pgid はの pid です)。そのため、 は独自のプロセス グループを開始できます。ps
perl
ps
perl
または、フォアグラウンドプロセスグループを変更することもできます。基本的には、ttyデバイスに、他のプロセスグループにSIGINTを送信するように指示します。Ctrl+C
perl -MPOSIX -e 'tcsetpgrp(0,getppid) or die$!; sleep 5'
そこでは、
perl
同じプロセス グループに残りますが、代わりに、フォアグラウンド プロセス グループの ID が親プロセス ID と同じであることをターミナル デバイスに伝えます (これについては上記の注記を参照してください)。