我正在运行一个while循环来读取文件中的每一行,然后使用该行的数据将进程分叉到子进程。在N行之后,我想等待子进程结束并继续接下来的N行等等。
它看起来像这样:
while ($w=<INP>) {
# ignore file header
if ($w=~m/^\D/) { next;}
# get data from line
chomp $w;
@ws = split(/\s/,$w);
$m = int($ws[0]);
$d = int($ws[1]);
$h = int($ws[2]);
# only for some days in the year
if (($m==3)and($d==15) or ($m==4)and($d==21) or ($m==7)and($d==18)) {
die "could not fork" unless defined (my $pid = fork);
unless ($pid) {
some instructions here using $m, $d, $h ...
}
push @qpid,$pid;
# when all processors are busy, wait for child processes
if ($#qpid==($procs-1)) {
for my $pid (@qpid) {
waitpid $pid, 0;
}
reset 'q';
}
}
}
close INP;
这不起作用。在第一轮进程之后,我得到一些PID等于0,@ qpid数组被混淆,文件开始在(显然)随机位置读取,来回跳跃。最终结果是文件中的大多数行读取了两到三次。有任何想法吗?
提前多多感谢,
S上。
答案 0 :(得分:4)
您是否正在unless ($pid)
内退出?
如果没有,那么你的孩子在运行命令后,会向数组添加零$pid
,并且通常继续运行应该是父进程代码
答案 1 :(得分:1)
我担心你的算法效率不高:
让基础进程fork将进程1转换为N.
如果进程2到N在进程1之前完成,那么在进程1完成之前不会启动任何新进程。
使用Parallel::ForkManager轻松获取正确的工作代码,而不是试图获得正确的实施细节。
use strict;
use warnings;
use Parallel::ForkManager;
my $pm = Parallel::ForkManager->new($MAX_PROCESSES);
while( my $w=<INP> ) {
next if $w=~m/^\D/; # ignore file header
chomp $w;
next unless match_dates( $w,
{ m => 3, d => 15 },
{ m => 7, d => 18 },
{ y => 2008 }, # Added this to show match_dates() capability.
);
my $pid = $pm->start and next;
.. Do stuff in child here ..
$pm->finish; # Terminate child
}
close INP;
# Returns true if ANY of the supplied date templates matches for ALL keys defined in that template.
sub match_dates {
my $string = shift;
my %target;
@target{qw( m d y )} = split(/\s/,$string);
DATE:
for my $date ( @_ ) {
my @k = keys %$match;
my $count = 0;
for( @k ) {
next DATE unless $date{$_} == $target{$_};
$count++;
}
return 1 if $count == @k; # All keys match
}
return;
}