
端末でパイプラインを実行しているとします。
$ a | b
端末から両方のプロセスに信号を送信する方法はありますか?それとも、2つのプロセスの1つの端末からのみ標準入力を読み取ることができますか?
b
以下を使用して標準入力から読み取ることができます。
open /dev/tty
a
しかし、これは私のテストでstdinを読むことができないようです。なぜ?
デフォルトでは、パイプctrlに送信したりstdinから読み込んだときにc信号は受信されません(私のテストによると)。ctrldb
a
答え1
Ctrl-Cなどの信号はstdinを介して渡されないことを明確にする必要があります。端末にCtrl-Cを入力すると、「Ctrl」と「C」は2つの生の文字でプロセスに直接渡されず、ttyドライバはそれをSIGINT信号として解釈し、信号をフォアグラウンドプロセスグループに送信します。
実行中にCtrl-Cを入力すると、
a | b
両方のプロセスがSIGINT信号を受け取ります。これをテストするには、コマンドの実行中にCtrl-Cを入力します。
tail -f /var/log/syslog | grep some_pattern
両方のプロセスが中断されたことを意味するシェルプロンプトがすぐに表示されます。
どうですか?
シェルにログインしたら、次のように入力します。会議、シェルで実行されるすべてのプログラムはこのセッションに属します。
セッションは制御端子、通常はキーボードから入力を受け取り、画面に出力します。このセッションのプロセスは、制御端末からstdinを読み取り、stdoutとstderrを制御端末に書き込み、制御端末から信号を受け取ります。
シェルパイプに接続されたプロセスはプロセスグループを形成する。たとえば、
proc1 | proc2 &
または好き
proc3 | proc2 | proc5
セッションは1つを持つことができますフォアグラウンドプロセスグループそして一つ以上バックグラウンドプロセスグループ。シェルをブロックして前景画面を占めるプロセスグループは、前景プロセスグループです。そして実行されるプロセスグループは
&
バックグラウンドプロセスグループになります。制御端末に「Ctrl-C」などのシーケンスを入力するたびに、信号は前景プロセスグループ内のすべてのプロセスに送信されます。
答え2
たくさん混ぜています。標準入力、出力、エラーファイル記述子(fds)、および端末fdは同じではありません。
ターミナルを開いてコマンドを入力すると、デフォルトでこれら3つのfd(stdin(0)、stdout(1)、stderr(2))がターミナルを「指定」しますが、これらのfdの1つ(たとえば「ls」)をリダイレクトします。できます。 non_existing_file 2>err"はエラーメッセージを"err"ファイルにリダイレクトし、端末には表示されません。
それでは、「open /dev/tty」行を指定したいと思います。この行は実際に端末を指し、違いを示すためにこのサンプルプログラムを確認してください。
パイプラインのしくみについて簡単に説明します。
2つのコマンドをパイプすると(「<」または「>」なし)、最初のコマンドはキーボードから入力を受け取り(入力を読み取る必要がある場合)、出力を2番目のコマンドの入力にリダイレクトします。プロセス「b」の標準的な「入力」は、もはや端末ではなく、プロセス「a」の出力である。
最後に、あなたの質問に答えるには、次の2つを知る必要があります。
1)フォアグラウンドでプロセスを開始すると、シェルはそのプロセスにターミナル制御を許可し、プロセスが完了するのを待ってからターミナルコントロールを再インポートし、キーボードから生成された信号はそのプロセスに送信されます。実行中のプロセスを制御します。
2)パイプコマンド(cmd1 | cmd2)を起動すると、シェルは最初に2つのプロセスを同じ「プロセスグループ」に配置します(詳細についてはジョブ制御を参照してください)。したがって、「a | b」の場合、両方のプロセスが同じプロセスグループにあるため、キーボードから生成された信号は両方のプロセスに送信されます。キーボードから生成された信号は、単一プロセスではなくプロセスグループ全体に送信されるためです。これがあなたの質問に答えることを願っています。不明な点がございましたら、お気軽にお問い合わせください。