2011-03-08 96 views
0

我想維護一個我已分叉的子組的pidlist數組,然後在它們退出時刪除它們(以限制我在任何給定的分叉進程數時間)。我認爲我可能很聰明,通過在刪除或拼接中使用@main :: pid_list來做到這一點,但沒有喜悅。我可以成功地彈出一個元素,但顯然它不會刪除正確的pid。任何想法如何處理,或者我會更好地做這個完全不同的方式?從信號處理函數(Perl)中的main ::更新數組

#!/usr/bin/perl -w 
use POSIX ":sys_wait_h"; 
use Data::Dumper; 

# Only allow 5 processes running at a time 

sub REAPER { 
    my $child = shift; 
    while (($child = waitpid(-1, WNOHANG)) > 0) { 
     # Need to remove child from pidlist here 
     #pop(@main::pid_list);      #This works 
     #delete($main::pid_list[$child]);   #This does not 

    } 
    $SIG{CHLD} = \&REAPER; 
} 

@pid_list =(); 
@files = (1 .. 20); 

foreach my $file (@files) { 
    my $processed = 'false'; 
    while ($processed eq 'false') { 

     print "Working on file: $file\n"; 
     $SIG{CHLD} = \&REAPER; 
     if (scalar(@pid_list) < 5) { 
      $pid = fork(); 
      if ($pid == 0) { 
       print "$$: Child Processing file #" . $file . "\n"; 
       sleep(10); 
       print "$$: Child done processing file #" . $file . "\n"; 
       exit(0); 
      } 
      push(@pid_list, $pid); 
      print Dumper(@pid_list); 
      $processed = 'true'; 
     } 
     sleep(1); 
    } 
} 

# Since we are at the end we need to wait for the last process to end 
print "PID: $$ End of parent program\n"; 

exit 0; 
+4

看起來像一個很好的地方,使用並行:: ForkManager – ysth 2011-03-08 07:26:36

回答

5

使用哈希表,而不是陣列。

sub REAPER { 
    my $child = shift; 
    while (($child = waitpid(-1, WNOHANG)) > 0) { 
     # Need to remove child from pidlist here 
     delete $main::pid_list{$child}; 
    } 
    $SIG{CHLD} = \&REAPER; 
} 

... 

if ((scalar keys %main::pid_list) < 5) { 
    ... 
    if ($pid != 0) { 
     ... 
     exit(0); 
    } 
    $main::pid_list{$pid}++; 
} 
+0

這是沒有必要使用'scalar'那裏,'<'已經暗示標量上下文。 – cjm 2011-03-08 06:53:16

+0

完美的作品 - 謝謝襪子傀儡! – OregonJeff 2011-03-08 15:30:15

0

嘗試@main::pid_list = grep $_ != $child, @main::pid_list;