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

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

ただいまの
回答率

90.50%

  • Python

    11741questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • Linux

    4438questions

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

  • UNIX

    430questions

    UNIXとは、AT&Tのベル研究所で開発されたコンピューター用のマルチユーザー・マルチタスクのオペレーションシステム(OS)です。政府や教育機関や研究所で広範囲に採用されています。

  • Processing

    328questions

    Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。

  • CPU

    52questions

プロセスの親子関係の親プロセスが正常終了するタイミング

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 404

プロセスの仕組みについて勉強しています。
なぜ、以下のようなアウトプットになるのか理解できません。os.fork()の箇所で子プロセスが生成され、「親プロセス: 69314」が2つ出力されると思っていましたが、どうして以下のような結果になるのでしょうか?print(f'親プロセス: {os.getpid()}')の箇所で親プロセスは、正常終了し、子プロセスが残った状態でprint(f'子プロセス: {os.getpid()}')が出力されているのでしょうか?
しかし、printは、システム関数であるため、printの処理が終わったからといって正常終了したことにはならないと思っています。

bash-3.2$ cat test.py
import os

if os.fork(): #os.fork()が実行されると0が返却され、子プロセスはelse内の処理に入りprint文を実行する
   print(f'親プロセス: {os.getpid()}')
else:
   print(f'子プロセス: {os.getpid()}')
bash-3.2$ python test.py
親プロセス: 69314
子プロセス: 69330
bash-3.2$
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+2

誤解がある気がします。

import os

if os.fork():
    print(f'親プロセス: {os.getpid()}')
else:
    print(f'子プロセス: {os.getpid()}')

このコードでforkするのは「os.fork()が呼ばれた(厳密には呼ばれたあとに内部でforkの処理が終わった)とき」です。os.fork()が返ってifが実行される時点では親プロセスと子プロセスに別れ、それぞれで別の道を歩んでいます。

子を孤児としてinitに看取らせる場合はこう。親がさっさと死んだあと、initが引き取ってwaitします。

import os
import time

if os.fork():
    print(f'親プロセス: {os.getpid()}')
else:
    time.sleep(3)
    print(f'子プロセス: {os.getpid()}')

これの理解も違う。

import os
import time

os.fork()
print('親プロセスは死んだ') # 親プロセスはforkした瞬間に死ぬ

for i in range(5):
   time.sleep(1)
   print(f'孤児として生きてる {i} : {os.getpid()}')

# 親プロセスはforkした瞬間に死ぬって、そんな訳無いでしょう。親と子でそれぞれ下のforが実行されます。だから10回出力されるんです。

import os
import time

print("親のpid", os.getpid())
os.fork()

for i in range(5):
   time.sleep(1)
   print(os.getpid())

""" =>
親のpid 21168
21169
21168
21169
21168
21169
21168
21168
21169
21169
21168
"""

forkの何たるか、というところから勘違いしている可能性大なので、勉強し直しましょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/06 15:27

    ありがとうございます!参考になります。

    キャンセル

check解決した方法

0

elseで抜けると正常終了することになる。
例えば、以下の例だと、for文のため、親プロセスが正常終了せず、生きたままになっている。

bash-3.2$ cat test2.py
import os
import time

os.fork() 
print('親プロセスは死んだ')
for i in range(5):
   time.sleep(1)
   print(f'孤児として生きてる {i} : {os.getpid()}')


出力結果

bash-3.2$ python test2.py
親プロセスは死んだ
親プロセスは死んだ
孤児として生きてる 0 : 69728
孤児として生きてる 0 : 69744
孤児として生きてる 1 : 69728
孤児として生きてる 1 : 69744
孤児として生きてる 2 : 69744
孤児として生きてる 2 : 69728
孤児として生きてる 3 : 69728
孤児として生きてる 3 : 69744
孤児として生きてる 4 : 69744
孤児として生きてる 4 : 69728

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/06 09:20

    「elseで抜けると終了」というのは表現としては曖昧に思えます。スクリプト上のコードが全て実行されそれ以上なにも実行することがなくなったら終了と表現した方がよいでしょう。
    ご質問のコードでいえば親は(A)を実行した後、if文の次にある文の実行を継続しますがそれ以上なにも書かれないのでそこでプロセスが終了します。子プロセスも同様で(A)のかわりに(B)を実行しますが、それ以降は親と同じ運命をたどります。
    if os.fork():
     print(...) # (A)
    else:
     print(...) # (B)

    キャンセル

  • 2019/02/06 15:29 編集

    ありがとうございます!言い方を間違えました。os.fork()は、0をかえすので子プロセスはelse内でprint文を実行するという理解です。

    キャンセル

  • 2019/02/07 01:50 編集

    >os.fork()は、0をかえすので
    子ではそうですが親側では子プロセスのpidが返りますよ。
    >子プロセスでは 0 が返り、親プロセスでは子プロセスの id が返ります。
    https://docs.python.jp/3/library/os.html#os.fork

    最初に起動されたときは当然(のちの)親プロセスしかいない訳ですが、forkはこの親プロセスをコピーして子を作るイメージです。親子の違いは主にpidとforkの返り値(細かいことを言い出すと他にもいろいろあると思いますが)。コピーされた後は、それぞれが別々に同じ位置から実行されます。
    親側ではforkで子のpidが返っているので条件がTrueになり、子側では0が返っているのでFalse……という動作ですね。

    キャンセル

  • 2019/02/07 11:01

    pidがかえるんですね。これで納得がいきます、腑に落ちました。ありがとうございます!

    キャンセル

同じタグがついた質問を見る

  • Python

    11741questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • Linux

    4438questions

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

  • UNIX

    430questions

    UNIXとは、AT&Tのベル研究所で開発されたコンピューター用のマルチユーザー・マルチタスクのオペレーションシステム(OS)です。政府や教育機関や研究所で広範囲に採用されています。

  • Processing

    328questions

    Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。

  • CPU

    52questions