2011-12-07 2 views
3

다중 처리 기능을 가진 작은 Perl 프로그램을 만들려고합니다. 내 요구 사항에 약간의 변화가 있기 때문에 비슷한 샘플 스크립트를 찾을 수 없습니다.Perl에서 여러 어린이를 포킹하고 양방향 통신을 위해 파이프를 사용하십시오.

STDIN에서 큰 로그 파일을 읽고 첫 번째 자식 프로세스에 첫 번째 N 개의 번호 (다시 큰 번호)와 두 번째 자식 프로세스에 다음 N 개의 줄을 줄 필요가 있습니다. 또한 상수 defined는 동시에 실행되도록 허용 된 하위 프로세스의 최대 수입니다. 최대 아동 수에 도달하면 부모는 한 아이가 직업을 마치고 또 다른 N 개의 전화 번호를 줄 때까지 기다릴 것입니다.

부모 프로세스는 각 자식 프로세스가 완료 될 때 반환 된 여러 줄 (5-10 줄) 출력을 수집하여 배열에 저장합니다. 그런 다음 부모는이 배열 내용을 계속 처리하고 결과를 최종적으로 표시합니다.

내가 수정하고 사용할 수있는 더 좋은 샘플 스크립트가 있습니까? 아니면 누군가가 여기에서 공유하여 도움을 줄 수 있습니까? 프로세스 상호 통신을 위해 파이프 만 사용하는 것이 더 편하고 가능한 한 더 단순하게 유지하는 것이 더 좋습니다.

편집 : 누군가가 IO :: Handle 모듈의 파이프를 통해서만 어떻게 수행 할 수 있는지 예제를 보여줄 수 있습니까?

답변

4

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; 
} 
+0

정확히 내가 원하는 것처럼 보입니다. 하지만 제한된 수의 Perl 모듈 만 사용할 수있는 제한된 환경에서이 스크립트를 실행합니다. IO :: Handle을 단독으로 사용할 수 있습니까? – meharo

-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();  
} 
관련 문제