Perl中的Fork不能在while循环中读取文件
我正在运行一个while循环,读取文件中的每一行,然后将该行的数据分叉给子进程。在N行之后,我想等待子进程结束,然后继续下N行,以此类推 它看起来像这样:Perl中的Fork不能在while循环中读取文件,perl,file-io,fork,Perl,File Io,Fork,我正在运行一个while循环,读取文件中的每一行,然后将该行的数据分叉给子进程。在N行之后,我想等待子进程结束,然后继续下N行,以此类推 它看起来像这样: while ($w=<INP>) { # ignore file header if ($w=~m/^\D/) { next;} # get data from line chomp $w; @ws = split(/\s/,$w);
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;
while($w=){
#忽略文件头
如果($w=~m/^\D/){next;}
#从行中获取数据
咀嚼$w;
@ws=拆分(/\s/,$w);
$m=int($ws[0]);
$d=int($ws[1]);
$h=int($ws[2]);
#一年中只有几天
如果($m==3)和($d==15)或($m==4)和($d==21)或($m==7)和($d==18)){
除非定义(my$pid=fork),否则die“无法分叉”;
除非($pid){
这里有一些使用$m、$d、$h的说明。。。
}
推送@qpid,$pid;
#当所有处理器都忙时,等待子进程
如果($#qpid==($procs-1)){
对于我的$pid(@qpid){
waitpid$pid,0;
}
重置“q”;
}
}
}
关闭INP;
这是行不通的。在第一轮处理之后,我得到了一些等于0的PID,@qpid数组被混淆了,文件开始在(显然)随机的地方被读取,来回跳跃。最终的结果是文件中的大多数行被读取两到三次。有什么想法吗
提前多谢了
除非($pid),否则您是否在
内部退出
如果没有,则您的孩子在运行命令后,将向数组中添加0的$pid
,并通常继续运行应该是父进程代码的内容我担心您的算法效率不高:
让基本进程分叉处理1到N
如果进程2到N在进程1之前完成,则在进程1完成之前不会启动新进程
不要试图获得正确的实现细节,而是使用来轻松获得工作代码
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;
}
使用严格;
使用警告;
使用并行::ForkManager;
my$pm=Parallel::ForkManager->new($MAX\u进程);
而(我的$w=){
下一步如果$w=~m/^\D/#忽略文件头
咀嚼$w;
下一步,除非匹配日期($w,
{m=>3,d=>15},
{m=>7,d=>18},
{y=>2008},#添加此项以显示match_dates()功能。
);
my$pid=$pm->开始和下一步;
…在这里做孩子的事。。
$pm->finish;#终止子项
}
关闭INP;
#如果提供的任何日期模板与该模板中定义的所有键匹配,则返回true。
子匹配日期{
我的$string=shift;
我的%目标;
@目标{qw(mdy)}=split(/\s/,$string);
日期:
为我的$date(@){
我的@k=keys%$match;
我的$count=0;
对于(@k){
下一个日期,除非$DATE{$}==$target{$};
$count++;
}
如果$count=@k;#所有键匹配,则返回1
}
返回;
}
请使用严格的
和使用警告
。这些pragma大大减少了调试过程中的痛苦。虽然他们不会帮助解决这个问题,但总的来说,他们确实起到了巨大的作用。