プログラムを実行した後、bashはバックグラウンドで何をしますか?

プログラムを実行した後、bashはバックグラウンドで何をしますか?

ターミナルの入力は、bashプロセスを介して現在実行されているプログラムにルーティングされますか、またはターミナルはbashプロセスで「接続が切断されて」新しいプログラムに接続され、bashが傍受または干渉するのを防ぎますか?

Bashはバックグラウンドで停止してプログラムの終了を待っていますか、それとも何かをしていますか?

ターミナルウィンドウを閉じるときにbashにシグナルを送信し、フォアグラウンドプロセスにシグナルを送信して閉じますか?それとも、bashまで伝播するフォアグラウンドプロセスにシグナルを送信しますか?

答え1

ターミナルの入力は、bashプロセスを介して現在実行されているプログラムにルーティングされますか、またはターミナルはbashプロセスで「接続が切断されて」新しいプログラムに接続され、bashが傍受または干渉するのを防ぎますか?

どちらもありません。パイプやリダイレクトのない単純なフォアグラウンドコマンドを想定すると、ユーザーの入力とユーザーへの出力はbashを介してルーティングされません。しかし、bashは干渉をブロックしません。 bashは単にブロックされません。努力する干渉。

プログラムがファイルまたは端末を開くと、読み書きのためのファイル記述子を受け取ります。 子プロセスは、親プロセスのオープンファイル記述子セットのコピーを継承します。

端末に何かを入力すると、標準入力を介してプロセスに渡されます。ユーザーに書き込むときに stdout または stderr に書き込みます。 Stdin、stdout、stderr はすべて、予測可能な ID を持つファイル記述子です。 POSIX 規格に従って、それぞれ 0 1 2 に番号が付けられます。したがって、Bashがプログラムを実行すると、まず子プロセスが生成されます。クロスそして、サブプロセスは同じstdin、stdout、およびstderr FDを自動的に継承します。したがって、子は自動的にまったく同じ端末を読み書きします。

「プログラムの実行」は、以下を呼び出して実行されます。クロスそれから実装する。パイプとリダイレクトは、代替のstdin、stdout、およびstderrを呼び出すことによって実装されます。デュープ2フォークとexecveの間。

したがって、「プログラム」は bash と同じ端末で直接読み取ることができます。これはbashや他のものが同じ端末で読み書きするのを防ぎません。 Bashが実際にこれを実行しようとすると、混乱が発生する可能性があります。マルチプロセス書き込みにより、すべてが予測不可能な順序で記録される可能性があります。複数のプロセスから読み取ると、一部のバイト(キー入力)があるプロセスに移動し、他のバイトが別のプロセスに移動されます。

Bashはバックグラウンドで停止してプログラムの終了を待っていますか、それとも何かをしていますか?

効果的に凍結します。もっと正確に言えば待っている。私が知っている限り、それは明示的に呼び出されます。waitpid()またはwait3()(シェルを実行しているUnixに応じて)子プロセスが終了するのを待ちます。

ターミナルウィンドウを閉じるときにbashにシグナルを送信し、フォアグラウンドプロセスにシグナルを送信して閉じますか?それとも、bashまで伝播するフォアグラウンドプロセスにシグナルを送信しますか?

申し訳ありません。この動作はすぐには覚えていません。私はターミナル[ウィンドウ]を閉じると、通常何も読み書きしなくても実行中のプロセスを終了すると思います。私はそれがEOFを引き起こす端末の読み取りに基づいているとは信じていません。。端末の閉鎖によりシグナル。正しい答えを見つけたら、答えを修正します。

私は、子供がキーボード割り込みキーシーケンスを効果的に傍受し、bashがキーシーケンスを受信できないようにすることができることを知っています。これが信号を傍受するのか、端末が信号をすべて生成するのを防ぐのかはわかりません。

答え2

まだ質問されていない質問は次のとおりです。プロセスを非同期的に(&を使用して)開始するとどうなりますが、これが&なしでコマンドを入力するのと異なるのはなぜですか?

ここで重要なのは「継承」だ。対話型シェルが何もしない場合は、プロンプト(PS1変数)を表示して標準入力を読みます。ウィンドウマネージャは、起動時にシェルと通信するために生成するストリームに書き込むキーストロークがないため停止します。

コマンド名を入力すると、シェルは独自に「フォーク」(コピー)し、子プロセスはシェルからstdin、stdout、stderrを継承します。その後、サブシェルはカーネルにコマンドを独自にロードするように指示します(「execve」)。

問題は、ウィンドウマネージャに同じストリームを読み込む2つのプロセス、つまり元のシェルとサブコマンドがあることです。何をすべきか?次に、あなたが入力した内容を誰が読むのでしょうか?

同期された「前景」サブアイテムの場合、サブコマンドはデータを取得する必要があります。したがって、シェルはstdinから読み込まれません。代わりに、子プロセスが終了し、その終了状態が利用可能になると、スリープモードに切り替わり、SIGCHLDによって起動されることが予想されます。したがって、2番目のフォアグラウンドサブプロセスを開始するように指示する方法はありません。

非同期「バックグラウンド」サブプロセスの場合、サブプロセスは標準入力接続が切断された状態でフォーク(/ dev / nullに接続)されます。 Stdoutとstderrはまだ接続されているため(リダイレクトされていない限り)、非同期プロセスは依然として端末に送信できます(回線同期はランダムになる可能性があります)。その後、シェルはプロンプトを表示し、次のコマンド(例: "jobs")を待ちます。別の非同期プロセスを開始したり、一度に1つのコマンドを実行したり、組み込みのシェルコマンドを処理したりすることで、多くのバックグラウンドタスクを同時に実行できます。各非同期サブプロセスが終了しても、SIGCHLD を受け取り、状態を収集し、タスクリストから削除するなどのタスクを実行できます。

端末を閉じると、シェルはウィンドウ入力を取得したストリームからEOFを取得すると疑われます。各子項目の開始時に設定される内部リストを使用して、すべての子項目を終了します。

答え3

理解すべき重要な違いは、端末とシェルの間です。端末は、コンピュータ画面でコマンドを入力し、テキストを読み、プログラム出力を受信するために使用するインタフェースです。一方、Shellはカーネルと対話してプログラムの実行を担当するオブジェクトです。

端末が「停止しない」。シェルがプロセスを完了するまで「待機」している間は、新しいプロンプトは表示されません。同じシステムで複数の端末を使用できます(これが私たちtmuxができることです!)。

端末でコマンドを入力するかプログラムを実行すると、端末はキーストロークを解析してシェルに渡します。次に、入力を解析してプロセスを実行します。入力がシェルに渡されると、端末は操作を完了しました。今やるべきことは、スクリプトが完了するのを待つだけです。

この説明は最後の質問にも答えになります。端末画面を閉じると、この信号は現在実行中のプログラムに伝播して終了します。

関連情報