質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Q&A

解決済

2回答

676閲覧

親プロセス終了後、子プロセスが端末に書き込みした場合の挙動について

akiyama3284pga

総合スコア186

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

0グッド

0クリップ

投稿2022/11/30 10:10

編集2022/11/30 11:53

以下のコードをubuntuで実行します。

import os, time n = os.fork() if n == 0: print("子pid == ", os.getpid()) print("親終了前、getppid() ==", os.getppid()) time.sleep(9) print("親終了後、getppid() ==", os.getppid()) # ★ time.sleep(200000) else: time.sleep(5) print("親終了します.")

本来、親が終了した場合には子はバックグラウンドに移行されると思います。
確かに本コードでも5秒経って親が終了した段階で、bashがフォアに戻り、プロンプトが復帰します。
しかし、★のprint()のように、制御端末に書き込みすると、プロンプトが子プロセスに横取りされ、これはprint()の次のsleep(200000)が終わるまで続きます。

これは、端末に書き込みが生じた場合には、何らかのシグナルが端末ドライバに発せられ、
フォアグランドに移行されているのでしょうか?
それとも、単にバックグラウンドから端末に出力されているだけでしょうか?(これだと子のsleep()の間プロンプトが使えない説明がつかない...)

--追記
TPGIDを見ますと、親終了前は、

bash 21415 21415 21415 3691 21795 pts/2 /usr/bin/python3 loop.py 21795 21415 21795 21415 21795 pts/2 /usr/bin/python3 loop.py 21795 21415 21827 21795 21795 pts/2

親終了後(print()とかした場合も、)は、

bash 21415 21415 21415 3691 21415 pts/2 /usr/bin/python3 loop.py 21795 21415 21827 2188 21415 pts/2

のようにきっちりbashのプロセスグループにフォアが帰っています。
つまり、フォアにはなっていないということがわかりました...

なのに、どうして端末はバックグラウンドであるはずのプロセスのsleep()状態となっているのか、まだここがわかりません。

--追記2
enterを押すことで、制御がbashに戻りました。
これは、あるプロセスをバックグラウンド実行(&)した際に、enter(return)を押すまで制御がシェルに戻らない仕様に関係する(同様のこと)だと思いました。
つまり、親が終了して子はバックに移行したが、その後何らかの標準出力が行われると、一度上と同じ動作になる。(つまり、enterを押すことですぐに制御が戻る....)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

matukeso

2022/11/30 12:01

>(これだと子のsleep()の間プロンプトが使えない説明がつかない...) これは本当ですか? Return押したらshellのpromptが出ると思いますが。
akiyama3284pga

2022/11/30 12:13

入れ違いで申し訳ありません。 先程自分の方でも間違いに気づきました。汗 少し整理して自己解決したいと思います。
guest

回答2

0

ベストアンサー

単にバックグラウンドから端末に出力されているだけでしょうか?

そうです。書き込み権限があれば、どんなプロセスからでも端末に出力できます(注1)。
端末を2つ開いてttyコマンドでデバイス名を調べ、例えば/dev/pts/1/dev/pts/2とすると、
/dev/pts/1の端末で、date > /dev/pts/2と実行すると、他方の端末に日時が表示されます。

enterを押すことで、制御がbashに戻りました。

これはEnterを押してプロンプトが表示されたのを見て、「制御がbashに戻りました」と思ったのでしょうが、
それは全くの勘違いです。
制御は親が終わった時点でbashに戻っています。Enterを押してプロンプトを出すことなく、いきなりコマンドを打ってもちゃんと実行されます。

例えば、上に書いた2つ目の端末で、日時が表示されて、

text

1[~~~] $ Wed Nov 30 21:43:30 JST 2022 2←カーソルはここ

の状態で、コマンドを打てばちゃんとと実行されます。

(注1:writeコマンドを使えば(書き込み権限がない)他ユーザーの端末にもメッセージを表示可能。異なるユーザーとのチャット用のコマンドです。)

投稿2022/11/30 13:03

otn

総合スコア84557

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

akiyama3284pga

2022/11/30 13:28

お世話になります。 いつも的確なご回答ありがとうございます。 今回も不明だった点がよくわかりました。 自分の方でも、プロンプトが表示されてない時でもしっかりコマンドを実行できることを確認いたしました。 TPGID等も重要なヒントになっていました。 また、入力においては、バックからはしようとするとsignalが入り、一切できないことも確認いたしました。 自分の見た資料が少し古いシェルを対象としたものであったようで、出力の方も自分のセッション内、フォアグラウンド以外からは特別な設定をしない限りできない、ような主旨のことを見たせいか、少し修正が必要でした。
otn

2022/11/30 15:46

シェルというか、端末の問題です。バックグラウンドからの出力時に、プロセスを止めるには、 stty tostop です。
akiyama3284pga

2022/11/30 23:59

ありがとうございます。 分けて考えていたつもりが、いつの間にか役割が一部ごちゃ混ぜになっていました。
guest

0

全面的に自分のミスがありました。

"
print()の次のsleep(200000)が終わるまで続きます。
"

ではなく、"enter(return)を押すまで戻らない"、というのが正しかったです。

バックグラウンドから標準出力があった場合、それを許すのか(フォアが動いているかどうか関係なく、割り込み的に表示するかどうか)は実装次第ですが、
許されていた場合には、表示した上で、returnされるまで一時的に帰らない状態になるのだと思いました。
また、親が終了して子がsleep(9)から起きるまでの間に別の1秒ごとにprint()するようなフォアグラウンドプロセスを起動した場合には、一瞬プロンプトに子のprint()が表示された後にまたフォアのプロセスの表示が続きました。

つまり、自分がいっていたバックがフォアに移行された というわけではなく、
バックから出力されただけ、という話になりました。

また、
・バックプロセスの結果等は、enter(return)を押したタイミングで出力される設計のよう。

投稿2022/11/30 12:28

編集2022/11/30 12:34
akiyama3284pga

総合スコア186

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問