Perl中的Fork不能在while循环中读取文件

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循环,读取文件中的每一行,然后将该行的数据分叉给子进程。在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;
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大大减少了调试过程中的痛苦。虽然他们不会帮助解决这个问题,但总的来说,他们确实起到了巨大的作用。