今日、おそらく簡単に説明できるが、私にとってはまったく予想外のことを発見しました。私は CentOS (および動作が同じ RHEL) を実行しています。ターミナルで bash を開き、gedit などのサブプロセスを開始します。ウィンドウは問題なく開きます。「ps」を実行すると、gedit の親プロセスが bash であり、その親プロセスが gnome-terminal であることがわかります。次に bash を停止すると、すべての子プロセスも停止するはずです。しかし、gedit は実行し続け、親が 1 (init) に変更されました。
シェルを正常に停止せずに強制終了しようとしましたが、結果は同じでした。シェルの代わりにターミナルを終了しようとしましたが、それでも結果は同じでした。X ボタンをクリックしてターミナルを閉じると、gedit も閉じられます。
そのような動作は予想していませんでした。nohup で gedit を起動しても驚きませんが、nohup がなくても... なぜ gedit は動作し続けるのでしょうか?
誰かが何か明かしてくれて、そこで何が起こっているのか知っているかもしれません。よろしくお願いします!
答え1
gedit、gvim、google-chromeなどのプログラムは自動的にバックグラウンドに切り替わります。これにより、
gedit /home/msw/ul-answer
新しいウィンドウをマップして、シェル プロンプトを戻します。これは悪い設計選択ではなく、通常はこれを上書きするオプションがあります。 コマンドgedit -w
と はgvim --nofork
制御端末から切り離されず、シェル プロンプトを戻しません。
プログラムがバックグラウンドで実行されるには、フォークしてから親が終了します。これにより、入力するとすぐに、gedit の通常のインスタンスが init (PPID == 1) の子になります。
mplayer や calibre などの他のプログラムは、頻繁に入力されないか、デバッグ情報を制御端末にダンプするため、自動的にバックグラウンドに移行しません。
奇妙な点を追加:
これをテストして strace の出力などを確認するのに少し時間を費やしたところ、gedit は自動的にバックグラウンドに移行していないようです。gvim について述べたことは依然として有効であり、スリープする時間はとうに過ぎているので、今のところはそのままにしておきます。
答え2
ターミナルウィンドウを閉じると、カーネルはSIGHUPbash にシグナルを送ります。すると、bash は各ジョブに SIGHUP を送信し、SIGHUP で gedit を終了します。
exit
またはCtrl+と入力するかD、SIGKILL で強制終了して bash を終了すると、ターミナル エミュレーターは子プロセスが終了したことを認識し、ウィンドウを閉じます。Gedit は影響を受けません。