perl进程队列

perl进程队列,perl,multiprocessing,Perl,Multiprocessing,我有一个Perl脚本,它派生了许多子进程。我希望有一些功能,如xargs--max procs=4--max args=1或make-j4,其中Perl将保持一定数量的进程运行,直到它用完为止 说fork四个进程并等待它们全部完成是很容易的,然后再fork另外四个进程,但是我想让四个或n个进程同时运行,一个进程完成就派生一个新进程 在Perl中有没有一种简单的方法来实现这样一个进程池?请查看--它完成了您描述的大部分工作。您可以设置最大进程数,并且回调函数可以在一个子进程完成后立即启动一个新的子

我有一个Perl脚本,它派生了许多子进程。我希望有一些功能,如
xargs--max procs=4--max args=1
make-j4
,其中Perl将保持一定数量的进程运行,直到它用完为止

说fork四个进程并等待它们全部完成是很容易的,然后再fork另外四个进程,但是我想让四个或n个进程同时运行,一个进程完成就派生一个新进程

在Perl中有没有一种简单的方法来实现这样一个进程池?

请查看--它完成了您描述的大部分工作。您可以设置最大进程数,并且回调函数可以在一个子进程完成后立即启动一个新的子进程(只要有工作要做)。

可以处理此要求

use Forks::Super MAX_PROC => 5, ON_BUSY => [ block | queue ];
fork()
的调用可能会被阻止,直到活动子进程的数量降至5以下,或者您可以向
fork
调用传递其他参数,并且要执行的任务可以排队:

fork { sub => sub { ... task to run in subprocess ... } }
当一个子流程完成时,队列上的另一个作业将启动


(我是本模块的作者)。

虽然我几乎总是使用CPAN模块,或者使用奇妙的AnyEvent模块编写一些东西,但我认为理解这些东西在引擎盖下是如何工作的很重要。这里有一个示例,它除了perl之外没有其他依赖项。同样的方法也可以用C编写,不会有太多麻烦

#!/usr/bin/env perl

use strict;

## run a function in a forked process
sub background (&) {
  my $code = shift;

  my $pid = fork;
  if ($pid) {
    return $pid;
  } elsif ($pid == 0) {
    $code->();
    exit;
  } else{
    die "cant fork: $!"
  }
}

my @work = ('sleep 30') x 8;
my %pids = ();
for (1..4) {
  my $w = shift @work;
  my $pid = background {
    exec $w;
  };
  $pids{$pid} = $w; 
}

while (my $pid = waitpid(-1,0)) {
  if ($?) {
    if ($? & 127) {
      warn "child died with signal " . ($? & 127);
    } else {
      warn "chiled exited with value " . ($? >> 8);
    }

    ## redo work that died or got killed
    my $npid = background {
      exec $pids{$pid};
    };
    $pids{$npid} = delete $pids{$pid};
  } else {
    delete $pids{$pid};

    ## send more work if there is any
    if (my $w = shift @work) {
      my $pid = background {
        exec shift @work;
      };
      $pids{$pid} = $w;
    }
  }
}

块和队列的区别是什么?
block
将使程序等待某些子进程完成,以便启动下一个任务<代码>队列将当前任务放入队列,并让程序继续运行。当其他子进程完成时,队列上的作业将异步启动。在分叉进程等待更多作业排队时,是否有办法使其作为池保持活动状态?我将我的作业成批排队,然后报告输出,但我希望分叉的进程保持活动状态。在Perl 5.30上,由于
:utf8
句柄上的
sysread()
的弃用,当通过CPAN安装此模块时,测试失败。测试为
t/44l管道.t