如何在Parallel :: ForkManager中获取子进程id?

时间:2009-11-04 10:20:16

标签: perl parallel-processing fork

  use LWP::Simple;
  use Parallel::ForkManager;


  @links=( 
    ["http://prdownloads.sourceforge.net/sweethome3d/SweetHome3D-2.1-windows.exe","SweetHome3D-2.1-windows.exe"], 
    ["http://prdownloads.sourceforge.net/sweethome3d/SweetHome3D-2.1-macosx.dmg","SweetHome3D-2.1-macosx.dmg"],
    ["http://prdownloads.sourceforge.net/sweethome3d/SweetHome3DViewer-2.1.zip","SweetHome3DViewer-2.1.zip"],

  );

  # Max 30 processes for parallel download
  my $pm = new Parallel::ForkManager(30); 

  foreach my $linkarray (@links) {
    my $pid = $pm->start and next; # do the fork

    my ($link,$fn) = @$linkarray;
    warn "Cannot get $fn from $link"
      if getstore($link,$fn) != RC_OK;

    print "$pid = $link is done ";

    $pm->finish; # do the exit in the child process
  }
  $pm->wait_all_children;

执行此操作后,我的pid为零

0 = http://prdownloads.sourceforge.net/sweethome3d/SweetHome3DViewer-2.1.zip is done 

0 = http://prdownloads.sourceforge.net/sweethome3d/SweetHome3D-2.1-macosx.dmg is done 

0 = http://prdownloads.sourceforge.net/sweethome3d/SweetHome3D-2.1-windows.exe is done

但现在我真的在想它是否真的在做分叉。为什么我在Parallel :: ForkManager中将所有时间都设为0作为pid?

编辑2

我有2次更改

my $pid = $pm->start ; # do the fork
流程ID的

$$

21892 = http://prdownloads.sourceforge.net/sweethome3d/SweetHome3D-2.1-windows.exe is done 

21893 = http://prdownloads.sourceforge.net/sweethome3d/SweetHome3D-2.1-windows.exe is done 

21892 = http://prdownloads.sourceforge.net/sweethome3d/SweetHome3D-2.1-macosx.dmg is done 

23120 = http://prdownloads.sourceforge.net/sweethome3d/SweetHome3D-2.1-macosx.dmg is done 

21892 = http://prdownloads.sourceforge.net/sweethome3d/SweetHome3DViewer-2.1.zip is done 

23146 = http://prdownloads.sourceforge.net/sweethome3d/SweetHome3DViewer-2.1.zip is done 

但现在我得到两次。为什么我得到这个?

4 个答案:

答案 0 :(得分:5)

不确定Parallel :: ForkManager实现,但如果它与标准fork()类似,则返回0,因为您处于子进程中。 Fork只会向父进程返回一个非零pid。

我忘了添加,在启动调用后给出'和next',代码的行为完全符合预期。

编辑2的注释:

由于您从启动调用中删除了'和next',因此父进程也在运行下载。我猜21892是父进程的pid,它将多次遍历循环

答案 1 :(得分:5)

关于Edit2下面的代码:

你改变了

my $pid = $pm->start and next;

my $pid = $pm->start ; # do the fork

现在你没有正确地做叉子。虽然之前只有孩子继续执行循环体,而父亲继续执行 next ,但现在两者都继续执行循环体。因此,您会看到父级的pid(21892)多次执行循环。

答案 2 :(得分:4)

看到那条线?

my $pid = $pm->start and next; # do the fork

父母获得pid,孩子只会看到0.如果你想从子进程中获取你的pid,只需使用魔术变量$$

更新:

对该行的引用并不意味着更改该行的邀请。但是看一下,很明显$ pid在行后面的代码中会为0,所以print $pid打印0而不是其他任何内容都不足为奇。

答案 3 :(得分:0)

forloop{
if (my $pid = $pm->start($linkarray)){
              print "pid-i-got-from-child=$pid and this code is running under pid=$$\n";
              next;
            }
... and then continue with code processing in child process...

}

这将为您提供子pid,并继续使用fork处理代码。