【问题标题】:How to use fork() in Perl?如何在 Perl 中使用 fork()?
【发布时间】:2011-11-29 22:07:13
【问题描述】:

我在一个数组中有数百个文件名。我想为数组中的每 4 个文件创建一个子进程,并让该子进程对这 4 个文件中的每一个执行一些操作。 (所以对于 100 个文件,我将创建 25 个进程。)

我在理解有分叉时处理行的顺序时遇到了一些麻烦。我在想我可以做这样的事情,但我被卡住了:

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

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

我认为这是不对的,我希望有人能指出我正确的方向。谢谢。

【问题讨论】:

    标签: perl fork


    【解决方案1】:

    除了使用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;
    

    【讨论】:

    • while (my @files4 = splice(@files, 0, 4)) {(虽然会破坏@files)
    • 既然您将$i 增加了4,那么切片时您不需要将其乘以4,对吧?
    • use List::Gen 'by'; for my $files4 (by 4 =&gt; @files) {do something with @$files4}
    【解决方案2】:

    使用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(0+@files);
    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
    }
    

    【讨论】:

      【解决方案3】:

      我会分组到一个数组中,然后让孩子处理那个组

      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);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-02
        • 2016-08-10
        • 1970-01-01
        • 2012-12-21
        • 1970-01-01
        • 2012-09-07
        • 2020-08-16
        • 1970-01-01
        相关资源
        最近更新 更多