Ctrl-Cでターミナル自体が強制終了されないのはなぜですか?


39

端末を開くと、端末が実行されます。

luvpreet@DHARI-Inspiron-3542:/$

開けたばかりです。それで、Ctrl+ を押すとC、なぜそれはそれ自体を殺し、端末を閉じないのですか??


21
ターミナルはターミナルで実行されていません
;

3
control-dが機能する理由:unix.stackexchange.com/a/110248/14305
ヤヌス

回答:


48

Ctrl+ Cは割り込み信号です。これを端末で入力すると、bashはSIGINTをフォアグラウンドでジョブに送信します。ジョブがない場合(ターミナルを開いたばかりの場合)、何も起こりません。ターミナルエミュレータプログラムはシェルで実行されるジョブではないため、シグナルを取得せず、閉じません。

コントロールキーで端末を閉じたい場合は、Ctrl+ D(EOF)を使用します。これにより、bashが終了します(端末も閉じます)。

参照:Bashの初心者のためのガイド信号に、より深く、信号処理のしくみ
注:コメントを投稿したので、この答えは編集されています


4
適切な用語は、シェルが信号を「トラップ」することです。別の話は、別のウィンドウ内からターミナルウィンドウを起動する場合です。ctrl + cを親ウィンドウに送信すると、子プロセスが強制終了されます。
セルギーコロディアズニー

1
さらに、X11サーバーからの特定の信号をトラップするようにGUIウィンドウに指示することもできます。これにより、未保存の作業を通知するポップアップを表示したり、ブラウザのようにタブを開いたりすることができます
Sergiy Kolodyazhnyy

8
@chrylisは、端末プログラムがctrl-c文字を送信するだけで、実際にはカーネルttyレイヤーがそれを信号に変換します。
Random832 19年

3
@chrylis:そして、ターミナル、またはその内部で実行されているプログラム(たとえば、テキストエディター)は、Ctl-Cを他のアクションに変換する可能性があります。
-jamesqf

3
bashctrl-cを押してもプログラムが終了するとは思わない。どのプロセスグループがアクティブであるかをカーネルに通知し、カーネルは端末プログラムからctrl-cを受信すると、そのプロセスグループにシグナルを生成します。
カスペルド

32

^Cキーストロークは、他のキーストローク*のように、魔法ではない-それがフォーカスを持っている方のプログラムにキーコードを送信します。(Xでは、キーコードは54 Cで、修飾子は0x4ですCtrl。)キーのストリームを受信するプログラムは、適切な処理を行います。多くのGUIアプリケーションでは、キーストロークがクリップボードにコピーされることに注意してください。

GUI端末エミュレータ(Konsoleなど)または仮想端末は、と解釈されるキーストロークを受信すると^C、次の3つのいずれかを実行できます。端末は内にある場合は、rawモード、そして実行中のプログラムが実行しないように、端末を求めている任意の特殊キーの取り扱い自体を、まっすぐプログラムにそれらを渡します。行編集などの高度な機能をサポートする一部のプログラムは、完全な生のキーストロークと処理されたテキスト行の間にある構成でキーボード入力を受け取ります。bashたとえば、キーストロークを一度に1つずつ受け取ります。^C端末によって解釈されますが、バックスペースキーはシェルにそのまま送信されます。

ただし、ほとんどのプログラムはクックドモードを使用し(rawではないため)、端末が実際にプログラムに送信する前にいくつかの基本的なキーストロークを解釈します(これがでバックスペースを使用できる理由ですcat)。このモードでは、端末自体が^CキーストロークをSIGINTシグナルに変換し、子プロセスに送信します。端末は信号を生成したため、混乱して終了することはありません。

  • SysRq 本当に魔法です。

明らかにここではあまり関係ありませんが、一般的なコンピューティングでは、もっと多くの魔法のキーストロークがあります。最も有名なのは、キーの組み合わせが魔法に非常に近いWindowsの世界でCtrl+ Alt+ Deleteです(Windowsを動作させるために使用でき、それ自体が非常に魔法です!)。ほぼすべてをオーバーライドしますSysRq。その意味ではかなり似ています。
KRyan

7
Bashはrawモードを使用しません-一度に1つの文字モード(つまりcbreak/ -icanon)を使用しisigますが、モードを設定したままにし、マップされたキーを押したときに実際の信号を受信します。SIGINT記述したとおりに動作することで処理し(行編集をキャンセルするだけでなく、ループで実行されている可能性のある内部コマンドもキャンセルします)、andを完全に無視SIGTSTPSIGQUITます。viなどの他のプログラムはそうではありません。
ランダム832

1
@KRyan Ctrl+ Alt+ Deleteは、今日よりもさらに魔法でした-blogs.msdn.microsoft.com/oldnewthing/20140912-00/?p=44083。私はLinuxを中心に考えていますが、Windowsが初期にこのような限られたリソースでユーザーフレンドリーで論理的なものにしたことで、しばしばかなりの驚きを覚えました。
ミューザー

一部のOSでは、別のプログラムがフォーカスを持っている場合でも、ターミナルエミュレーターが実行する前に、システム(私が推測するウィンドウマネージャー)が実際にキーを押します。キーボードショートカットを設定してウィンドウをスナップし、アプリケーションを開き、スクリプトをトリガーすると、押されたキーがターミナルエミュレータに送信される前に、設定したショートカットがチェックされます。また、アプリケーションを開いていない場合の別の例で^cは、ウィンドウマネージャーは終了しません:)。時のもので、生/調理文字にコメントすることができますが、答えはそのキーストロークが発生している方法については上のスポットではありませんSIGINT
アジャイ

2
調理モード(生ではないため)」:私は...言葉がありません。これらすべての年後、私は接続を確立しませんでした。
-isanae

8

^C通常stty -aSIGINTシグナル(を参照)にマッピングされます(を参照man 7 signal)。

未捕捉SIGINTは実行中のプロセスを中断しますが、...

SIGINT プロセスが動作を指定できるシグナルの1つです(「シグナルのキャッチ」)。

「ターミナル」と呼ばれるものがキャッチしSIGINT、仕事に戻ります。


7

初心者のとき、コマンドラインを使用しているときに、実際には2つの別個のプログラム、ターミナルとシェル(bashなど)を使用していた部分がありませんでした。

シェルはおそらくご存知のとおり、入力コマンドまたはスクリプトとしてそれらを実行し、それらを実行して出力を出力するプログラムです。

反対側の端末は、ユーザーとプログラム(このプログラムは通常bashやfishのようなシェルです)の中間にいる男性のようなものです。端末が行うことは、たとえばキーボードから入力を読み取り、その入力を何らかの方法で処理し、他のプログラム(bash)にリダイレクトすることです。

また、これは他の方法でも機能します。他のプログラムが何かを出力すると、その何かが端末にリダイレクトされ、その何かを画面に出力するのは端末の仕事です。入力を取得して画面に出力するまでの間に、端末は取得した入力をさまざまな方法で解釈できます。

たとえば、プログラムが次のシーケンスを出力する場合:

\e[0;31m some extra foobar text

ターミナルは、赤い文字で「いくつかの余分なfoobarテキスト」を画面に出力します。これは、ターミナルがその奇妙なコードを特別な方法処理することを選択するためです。コードは、次の出力を赤で印刷するようにヒントを与えます。

同様に、ユーザーがを押すCtrl - Cと、これに関する唯一の特別なことは、端末が特別な方法でそれを処理することを選択することです。このキーシーケンスに関して他に特別なことはありません。具体的には、これは、端末内で実行されているプロセス、つまりシェルに割り込み信号(SIGINT)を送信することを示唆しています。その時点でシェルによって生成され、現在フォアグラウンドで実行されているプログラムが存在する場合、そのプログラムも信号を受信します。現在、シェルにはこのシグナル用の特別なハンドラーがあり、何も起こりません。ただし、ほとんどのプログラムにはデフォルトのハンドラがあり、SIGINTの場合は終了します。


5

すべてのシグナルには、デフォルトアクションが関連付けられています。シグナルのデフォルトのアクションは、スクリプトまたはプログラムがシグナルを受信したときに実行するアクションです。

Ctrl+ Cは、「割り込み」シグナル(SIGINT)を送信します。これは、デフォルトで、フォアグラウンドで実行中のジョブへのプロセスを終了します。

Ctrl+ Dは、標準入力でEOFを登録する必要があることを端末に通知します。bashは、終了を望んでいると解釈します

プロセスは、INTシグナルを無視することを選択できます。Bashは、インタラクティブモードで実行している場合は無視します。

マニュアルから:

bashは、トラップがない場合にインタラクティブである場合、SIGTERMを無視し(kill 0がインタラクティブシェルを強制終了しないように)、SIGINTがキャッチされて処理されます(ビルトイン待機が割り込み可能になるように)。すべての場合において、bashはSIGQUITを無視します。ジョブ制御が有効な場合、bashはSIGTTIN、SIGTTOU、およびSIGTSTPを無視します。


トラップでそれを理解する:

トラップは、ハードウェア信号やその他のイベントに応答するシェルに組み込まれた機能です。シェルがシグナルまたは他の特別な条件を受信したときに実行されるハンドラーを定義およびアクティブ化します。

trap [-lp] [arg] [sigspec …]

-l シグナル名とそれに対応する番号のリストを出力します。
-p各SIGNAL_SPECに関連付けられているトラップコマンドを表示します。

argは、シェルがシグナルsigspecを受け取ったときに読み込まれ、実行されます。各sigspecは、シグナル名またはシグナル番号です。シグナル名は大文字と小文字を区別せず、SIGプレフィックスはオプションです。

場合のsigspecがある0またはEXIT、argが時にシェルが終了実行されます。これを理解するには、.bashrcファイル内の次の行を編集してからターミナルを閉じて開きます。

trap 'notify-send "Ctrl D pressed"' 0

Ctrl Dはexit、ターミナルを終了するコマンドに似ています。

インタラクティブモードであっても、INT信号を受信したときにBashを終了したい場合は、次のものをに追加できます~/.bashrc

trap 'exit' INT

または

trap 'exit' 2

1
合法らしい!!
-luv.preet
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.