当我在循环中包含fork()
函数调用时,循环执行的次数超过了预期的时间。为了简单起见,我仅选择了两次迭代;您可以进行更多测试。
我尝试设置autoflush on
,但这似乎不起作用。
use strict;
use warnings;
use IO::Handle;
$|++; #autoflush on
STDOUT->flush();
for my $i (1 .. 2) {
print "Normal => $i\n";
}
print "\n";
for my $i (1 .. 2) {
my $pid = fork();
if(not defined($pid)) {
die "cannot fork\n";
} elsif (not $pid) {
print "Child => $i\n";
} else {
print "Parent => $i\n";
wait();
}
}
实际输出
Normal => 1
Normal => 2
Parent => 1
Child => 1
Parent => 2
Child => 2
Parent => 2
Child => 2
预期产量
Normal => 1
Normal => 2
Parent => 1
Child => 1
Parent => 2
Child => 2
请帮助我了解这里出了什么问题。
答案 0 :(得分:3)
您最终致电fork()
三遍 ,总共进行了四个进程。
以下是可能产生您所看到的输出的一种执行序列:
Process 1 Process 2 Process 3 Process 4
$i == 1
fork----------->$i == 1
"Parent 1"
"Child 1"
$i == 2
fork--------------------------->$i == 2
"Parent 2"
"Child 2"
$i == 2
fork--------------------------->$i == 2
"Parent 2"
"Child 2"
wait
reaped
zombie zombie
答案 1 :(得分:3)
如Jim Garisson's answer中所述,您最终调用了fork
3次,因此创建了3个附加进程。
这是一个更简单的示例,它可以帮助您了解正在发生的事情:
say "Start";
fork();
say "Middle";
fork();
say "End";
可能的输出之一是:
Start
Middle
Middle
End
End
End
End
最初的过程说“开始”,然后分叉,因此您最终得到两个过程,每个过程说“中间”,然后分叉,每个过程又创建了一个附加过程,因此最终您说了4个过程,说“结束” “。
图形表示可能会有用:
"Start"
|
fork()
|
------------------------------
| |
"Middle" "Middle"
| |
fork() fork()
| |
--------------- ---------------
| | | |
"End" "End" "End" "End"
答案 2 :(得分:1)
类似的问题和答案可以在https://stackoverflow.com/a/8318556/542995
中找到因为您的代码将有第一个孩子开始与父代完全相同的迭代。
因此,只是为了简单起见,以防止出现额外的循环。您可能必须exit
子级作业,并将wait();
置于父级,以在单独的循环中响应已完成的作业。而且,这将达到您的期望。
use strict;
use warnings;
my $n = 2;
for my $i (1 .. $n) {
my $pid = fork;
if (not $pid) {
print "Child: $i\n";
exit;
} else {
print "Parent $i\n";
}
}
for (1 .. $n) {
wait();
print "Job finished\n";
}
输出:
Parent 1
Parent 2
Child: 1
Child: 2
Job finished
Job finished