我正在尝试创建一个具有多处理功能的小型Perl程序。由于我的要求中存在一些小的变化,我无法在任何地方找到任何类似的示例脚本。
我需要从STDIN读取一个大的日志文件,并将第一个N号码(一个大号码)再次给第一个子进程,然后将第二个N行给第二个子进程等。我还有一个常量定义这是允许并发运行的最大子进程数。一旦达到最大子女数,父母将等待孩子完成其工作,并给予另外N行。
父进程还会收集每个子进程在完成时返回的多行(5-10行)输出并将其存储在数组中。然后,Parent继续处理此数组内容并最终显示结果。
是否有更好的示例脚本我可以修改和使用,或者有人可以通过在这里共享来帮助我吗?我更喜欢只使用管道进行流程互通,并尽可能简化事务。
编辑: 有人能举例说明如何只使用IO :: Handle模块中的管道来实现这个目标吗?
答案 0 :(得分:5)
使用Forks::Super
,可以轻松限制同时进程的数量并处理进程间通信。例如,
use Forks::Super MAX_PROC => 10, # allow 10 simultaneous processes
ON_BUSY => 'queue'; # don't block when >=10 jobs are active
@loglines = <>;
# set up all the background jobs
while (@loglines > 0) {
$pid = fork {
args => [ splice @loglines, 0, $N ], # to pass to sub, below
child_fh => "out", # make child STDOUT readable by parent
sub => sub {
my @loglines = @_;
my @result = ... do something with loglines ...
print @results; # use $pid->read_stdout() to read in child
}
};
}
# get the results
while ($pid = waitpid -1, 0) {
last if $pid == -1;
my @results_from_job = $pid->read_stdout();
push @results, @results_from_job;
}
答案 1 :(得分:-1)
我发现线程对于这种过程来说要简单得多。您需要线程和Threads :: Queue模块。该过程是设置一个队列来提供工作线程,一个队列让他们返回结果。工作线程只是一个读取记录,处理记录并将结果发回的函数。我只是将这些代码放在一起,并没有对它进行测试,因此它可能是错误的,但我认为显示了一般的想法:
use threads ();
use Thread::Queue;
#
#
# Set limit on number of workers
#
my $MAX_THREADS = 5;
my $EOD = "\n\n";
#
#
# Need a queue to feed the workers
# and one for them to return results
#
my $Qresult = Thread::Queue->new();
my $rec;
my $n;
#
#
# load STDIN into the input queue
#
my $Qin = Thread::Queue->new(<>);
#
#
# start worker threads
#
for($n = 0; $n < $MAX_THREADS; ++$n)
{
async{ProcessRecord($n);};
$Qin->enqueue($EOD); # need terminator for each
}
#
#
#
# Wait for the results to come in
#
$n = 0;
while($n < $MAX_THREADS)
{
$rec = $q->dequeue();
if($rec eq $EOD)
{
++$n;
next;
}
:
:
:
#-- process result --#
:
:
:
threads->yield(); # let other threads get a chance
sleep 1;
}
exit;
######################################
#
#
# Worker threads draw from the queue
# when a "terminator" is read, quit;
#
sub ProcessRecord
{
my $rec;
my $result;
while(1)
{
$rec = $Qin->dequeue();
last if $rec eq $EOD;
:
:
:
#-- process record --#
:
:
:
$Qresult->enqueue($result);
threads->yield(); # let other threads get a chance
}
threads->exit();
}