perlでParallel::ForkManagerを用いて並列処理
perlで並列処理
ダウンローダーやアップローダー等を実装する際、
並列処理が必要になることがある。
Perlはスレッド対応にはなっているものの、スレッド間共有などの必要がなければフォークを使用した方が無難。
何も使わずにフォークを使用するには、子プロセスの終了通知「シグナル」を受け取る制御が必要だが、
Parallel::ForkManagerを使用することで、この作業を回避することができる。
rei1)丸腰で書く場合=子プロセスの終了したシグナルを受け取る。
use strict; use POSIX(); sub reap { while(($child = waitpid(-1,&POSIX::WNOHANG)) > 0){ #wait pidをroopするのは print "Parent: reaped $child\n"; } $SIG{CHLD} = \&reap; } $SIG{CHLD} = \&reap; for my $i(1..10){ my $pid = frok(); if(! defined $pid){ die "fork() failed..:$!"; } if(! $pid){ #child process print "Child: $$\n"; sleep rand(5); exit 0; } }
rei2)Parallel::Forkmanageを用いてforkする処理
use strict; use LWP::UserAgent; use Parallel::ForkManager; my @urls = wq( http://www0.example.com/ http://www1.example.com/ http://www2.example.com/ http://www3.example.com/ ); #max 5 process fork my $pm = Parallel::ForkManager->new(5); foreach my $url(@urls){ $pm->start and enxt; eval{ my $uri = URI->new($url); my $ua = LWP::UserAgent->new(); $ua->mirror($uri,$uri->host().'.html'); }; $pm->finish; }
シグナル処理とは?
Perl5.7.3以前=>unsafed_signal = perl binallyがシグナルを受け取った瞬間にハンドラが呼び出しされる
perl5.7.3以降=>delay_signal = perl内 one step終了後にハンドラが呼び出し
#Perlで使用できるシグナル一覧
$perl -MConfig -e 'print $Config{sig_name}, "\n"' ZERO HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF ...
#たとえば、Ctrl+Cのシグナルを受け取る
$SIG{INT} = sub {warn "got SIGINT!"; exit 1};