2011-11-29 21 views
5

我在數組中有數百個文件名。我想爲數組中的每4個文件創建一個子進程,並讓那個孩子爲這4個文件中的每一個都做一些事情。 (因此,對於100個文件,我將創建25個進程。)如何在Perl中使用fork()?

我在理解fork時處理行的順序時遇到了一些麻煩。我想我可以做這樣的事情,但我卡住:

foreach $file (@files) { 
if ($f++ % 4 == 0) { 
    my $pid = fork(); 

    if ($pid) { 
    push(@childs, $pid); 
    } 
    elsif ($pid == 0) { 
    ... do stuff to $file ... 
    } 
} 

我不認爲這是正確的,我希望有人能指出我在正確的方向。謝謝。

回答

11

除了您在使用fork時遇到的麻煩之外,您還似乎無法將@files陣列劃分爲四個較小的文件集。也許是這樣的:

for (my $i = 0; $i < @files; $i += 4) { 

    # take a slice of 4 elements from @files 
    my @files4 = @files[$i .. $i + 3]; 

    # do something with them in a child process 
    if (fork() == 0) { 
     ... do something with @files4 ... 
     exit; # <--- this is very important 
    } 
} 

# wait for the child processes to finish 
wait for 0 .. @files/4; 
+1

'而(我@ files4 =剪接(@files,0,4)){'(破壞@files,雖然) – ysth

+0

由於你將'$ i'增加了4,所以在切片時不需要將它乘以4,對吧? – itzy

+2

'使用List :: Gen'by';對於我的$ files4(按4 => @files){用@ $ files4做某事}' –

1

我會組一個數組,並讓孩子處理該組

my $group = [] 
foreach my $file (@files) { 
    push @$group, $file; 

    if(scalar(@$group) % 4 == 0) { 
     my $pid = fork; 
     die "Unable to fork!" unless defined $pid; 
     push @childs, $pid if $pid; 
     children_work($group) unless $pid; 
     $group = []; 
    }   
} 

sub children_work { 
    my $group = shift; 

    // child, work with $group 
    exit(0); 
} 
3

使用Parallel::ForkManager

use Parallel::ForkManager qw(); 

my $pm = Parallel::ForkManager->new(int(@files/4)); 
for my $file (@files) { 
    my $pid = $pm->start and next; 

    ... do something with $file ... 

    $pm->finish; # Terminates the child process 
} 

注意,這仍然創造100點的過程,它只是將其限制爲25個併發。

如果你真的只想要25流程,您可以使用以下命令:

use List::Util   qw(min); 
use Parallel::ForkManager qw(); 

my $pm = Parallel::ForkManager->new([email protected]); 
while (@files) { 
    my @batch = @files[0..min(4, $#files)]; 
    my $pid = $pm->start and next; 

    for my $file (@batch) { 
     ... do something with $file ... 
    } 

    $pm->finish; # Terminates the child process 
}