如何从子进程中传递变量(由Parallel :: ForkManager派生)? [英] How to pass a variable from a child process (fork by Parallel::ForkManager)?

查看:95
本文介绍了如何从子进程中传递变量(由Parallel :: ForkManager派生)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的查询:

在下面的代码中,我试图将打印的$commandoutput[0]转移或传递到即将到来的子例程中.跟随吗?

In the following code i had tried to bring the print $commandoutput[0] to be shifted or passed into the upcoming subroutine.i tried the shift to pass it.But i failed with it.Can you please help me the right way to follow?

代码:

my $max_forks = 4;

#createThreads();
my %commandData;
my @arr = (
   'bhappy',  'bload -m all -l -res CPUSTEAL',
   'bqueues', 'bjobs -u all -l -hfreq 101'
);

#print @arr;
my $fork = new Parallel::ForkManager($max_forks);
$fork->run_on_start(
   sub {
      my $pid = shift;
   }
);
$fork->run_on_finish(
   sub {
      my ( $pid, $exit, $ident, $signal, $core ) = @_;
      if ($core) {
         print "PID $pid core dumped.\n";
      }
      else { }
   }
);
my @Commandoutput;
my $commandposition = 0;
for my $command (@arr) {
   $fork->start and next;
   my @var = split( " ", $command );
   $commandoutput[$commandposition] = `$command`;
   $commandposition++;
   $line = $commandoutput[0];

# print $line;
   $fork->finish;
}
$fork->wait_all_children;

#print Dumper(\%commandData);
print $commandoutput[0];

在这里我试图将打印$commandoutput[0]存储在子程序内部的变量中.在这里,我介绍了如何将变量从外部传递到子程序内部.

Here i had tried to store the print $commandoutput[0] in the variable inside the subroutine.I gated here how to pass the variables from outside to inside the subroutine.

sub gen_help_data
{
  my $lines=shift;
  print $lines;
}

推荐答案

startfinish之间的代码在单独的进程中运行,而父级和子级不能访问彼此的数据(即使它们的变量碰巧具有相同的名称,它们也不同).这是分叉的第一件事,它使用自己的数据创建了一个单独的进程.

The code between start and finish runs in a separate process and the parent and child cannot access each other's data (even if their variables happen to have the same name, they are different). This is the first thing about forking, that it creates a separate process with its own data.

但是此模块确实提供了一种机制,您可以通过该机制将数据从子级传回. 参见在文档中从子流程中检索数据结构.

But this module does provide a mechanism by which you can pass data back from a child. See Retrieving data structures from child processes in docs.

您首先需要向finish提供对孩子想要返回的数据结构的引用.在您的情况下,您想返回标量$commandoutput[0],因此

You first need to supply to finish a reference to the data structure that the child wants to return. In your case, you want to return a scalar $commandoutput[0] so do

$fork->finish(0, \$commandoutput[0]);

然后在回调中找到此引用作为最后一个第六个参数.您的代码遗漏了一个.因此,您需要在回调中

This reference is then found in the callback as the last, sixth, parameter. The one your code left out. So in the callback you need

my %ret_data;  # to store data from different child processes

$pm->run_on_finish( 
    sub { 
        my ($pid, $exit, $ident, $signal, $core, $dataref) = @_; 
        $ret_data{$pid} = $dataref;
    }
);

此处$dataref\$commandoutput[0],它作为作为进程ID的键的值存储在%ret_data中.因此,在foreach完成后,您可以在%ret_data

Here $dataref is \$commandoutput[0], which is stored in %ret_data as the value for the key which is the process id. So after the foreach completes you can find all data in %ret_data

foreach my $pid (keys %ret_data) {
    say "Data from $pid => ${$ret_data{$pid}}";
}

在这里,我们取消引用$ret_data{$pid}作为标量引用,因为您的代码将其返回.

Here we dereference $ret_data{$pid} as a scalar reference, since your code returns that.

请注意,数据是通过写出文件来传递的,如果发生了很多事情,这可能会很慢.

Note that the data is passed by writing out files and that can be slow if a lot is going on.

这是一个完整的示例,其中每个子级将其传递给finish来返回数组引用,然后在回调中对其进行检索.有关其他示例,请参见这篇文章.. >

Here is a full example, where each child returns an array reference, by passing it tofinish, which is then retrieved in the callback. For a different example see this post.

use warnings;
use strict;
use feature 'say';

use Parallel::ForkManager;    
my $pm = Parallel::ForkManager->new(4); 

my %ret_data;

$pm->run_on_finish( sub { 
    my ($pid, $exit, $ident, $signal, $core, $dataref) = @_; 
    $ret_data{$pid} = $dataref;
});

foreach my $i (1..8)
{
    $pm->start and next;
    my $ref = run_job($i);
    $pm->finish(0, $ref);
}
$pm->wait_all_children;

foreach my $pid (keys %ret_data) {
    say "$pid returned: @{$ret_data{$pid}}";
}

sub run_job { 
    my ($i) = @_;
    return [ 1..$i ];  # make up return data: arrayref with list 1..$i
}

打印


15037 returned: 1 2 3 4 5 6 7
15031 returned: 1 2
15033 returned: 1 2 3 4
15036 returned: 1 2 3 4 5 6
15035 returned: 1 2 3 4 5
15038 returned: 1 2 3 4 5 6 7 8
15032 returned: 1 2 3
15030 returned: 1

这篇关于如何从子进程中传递变量(由Parallel :: ForkManager派生)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆