アプリ版:「スタンプのみでお礼する」機能のリリースについて

perlのfork機能を使いたい者ですが、その挙動について質問しています。

ここ数日fork機能について勉強しましたが、
その挙動がどうでしても理解できないので、質問をさせていただいています。

質問内容を具体的にするため、以下に簡単なコードを書いておきます。
#!/usr/bin/perl
use strict;

my $i=0;

while ($i<3)
{
if(fork())
{
print("parent hello -> $i\n");
last;
}
else
{
print("child hello -> $i\n");
sleep 3;
print("child exit -> $i\n");
$i++;
}
}
print("parent finish\n");

このコードをlinux上で起動させますと、下記の結果が得られました。
parent hello -> 0
parent finish
child hello -> 0
child exit -> 0
parent hello -> 1
parent finish
child hello -> 1
child exit -> 1
parent hello -> 2
parent finish
child hello -> 2
child exit -> 2
parent finish

ここから質問です。
上記の結果の中で自分が理解できないのは、
なぜ、「parent finish」が4回も出てくるのかということです。

自分の理解している部分では、「parent finish」はwhile loopの外にあるので、
「parent finish」をプリントするには、一度while loopを出る必要があると思います。
しかし、それが2、3回と続いてプリントされていることがなぜなのか理解できません。

理想としては、
parent hello -> 0
child hello -> 0
child exit -> 0
parent hello -> 1
child hello -> 1
child exit -> 1
parent hello -> 2
child hello -> 2
child exit -> 2
parent finish
という具合に、「parent finish」を一回だけ表示させたいのですが、それは可能でしょうか?

ご教授をお願いします。よろしくお願いします。

A 回答 (2件)

プロセスIDを付けると何がおこっているのかわかりますよ。



以下、$$はプロセスIDを表わしています。表示がくずれるので空白2文字を全角空白にし
ていることに注意。
use strict;
use warnings;

my $i = 0;

while ( $i < 3 ) {
  if ( fork() ) {
    print "parent($$) hello -> $i\n";
    last;
  }
  else {
    print "child($$) hello -> $i\n";
    sleep 3;
    print "child($$) exit -> $i\n";
    $i++;
  }
}
print "parent($$) finish\n";

---
$ perl -w foo.pl
parent(24503) hello -> 0
parent(24503) finish
child(24504) hello -> 0
child(24504) exit -> 0
parent(24504) hello -> 1
parent(24504) finish
child(24510) hello -> 1
child(24510) exit -> 1
parent(24510) hello -> 2
parent(24510) finish
child(24511) hello -> 2
child(24511) exit -> 2
parent(24511) finish
    • good
    • 0
この回答へのお礼

ありがとうございます。
確かにプロセスIDを表示するとわかりやすかったです。

理解した部分では、
fork -> プロセスが2つ作成される(ここでは、24503と24504)。
そのうちの一つ(24503)は、if statement内にある”parent(24503) hello -> 0”を経て、
lastがあるため、
while loopから抜け出て、最後の”parent(24503) finish”(ここでは、24503プロセスが終了している)がプリントされる。
先に作成された別のプロセス(24504)は、elseに入り、プリントを経て、$iをインクリメントして、while loopのチェックを受け、次につながる。

このため、複数回"parent($$) finish\n"がプリントされていたのですね。

勉強にもなりましたし、大変スッキリしました。
ありがとうございました。

お礼日時:2014/05/18 06:25

ん~と, どこが不思議なのかわからんのだけど.... fork で生まれた子プロセスでも last してるよね.

    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!