ここでは、コールバックが子プロセスの終了時に正しく実行されるように使用する方法の例を示します。この方法の
使用はfork
-ing後、ループ内のwaitpid -1, POSIX::WNOHANG
を呼び出すのと同じです。これは最大出力(30
)よりもフォークして出力を見やすくし、子プロセスが終了するとコールバックが正しく実行されることを示します。これらの数字を変更して、完全な操作を確認します。
多くのコードは診断用です。出力の子を追跡するには、10*$i
で終了します。匿名配列[...]
に返されるデータは、同じ目的のための説明文字列です。 reap_finished_children
が完了するとすぐに、$number_running
がコールバックで削減されます。このため、$curr
変数が必要です(これも診断用です)。
start: Started 4656, running: 1
start: Started 4657, running: 2
start: Started 4658, running: 3
Running: 4656 4658 4657
Kid #1 slept for 1, exiting
Cleared 4656, kid #1 exited with 10
Remains: 2. Data: gone-4656
Kid #2 slept for 10, exiting
Cleared 4657, kid #2 exited with 20
Remains: 1. Data: gone-4656 gone-4657
Kid #3 slept for 20, exiting
Cleared 4658, kid #3 exited with 30
Remains: 0. Data: gone-4656 gone-4657 gone-4658
を印刷します。これは、wait_for_available_procs($n)
利用可能なプロセススロットが利用可能になるまで待つことによって直接行うことができます。 $n
が指定されていない場合、デフォルトはになります。
$MAX
が$n
に使用されている場合、多くのスロットはバッチ全体が完了した時点でのみ使用可能になります。 $n
の使用方法は、実行時に決定することもできます。
モジュールの操作のいくつかの詳細
子はSIGCHLD
信号が、それは子供がなくなっていることを知っている(と避けるためにキャッチする必要があります親に送られ、終了するとゾンビ、最初に)。これは、wait
またはwaitpid
をコード内またはSIGCHLD
ハンドラ(ただし1か所のみ)で実行します。 fork
,Signals in perlipc
,waitpid
およびwait
を参照のこと。我々は、方法wait_all_children
sub wait_all_children { my ($s)[email protected]_;
while (keys %{ $s->{processes} }) {
$s->on_wait;
$s->wait_one_child(defined $s->{on_wait_period} ? &WNOHANG : undef);
};
}
で使用さ
sub wait_one_child { my ($s,$par)[email protected]_;
my $kid;
while (1) {
$kid = $s->_waitpid(-1,$par||=0);
last if $kid == 0 || $kid == -1; # AS 5.6/Win32 returns negative PIDs
redo if !exists $s->{processes}->{$kid};
my $id = delete $s->{processes}->{$kid};
$s->on_finish($kid, $? >> 8 , $id, $? & 0x7f, $? & 0x80 ? 1 : 0);
last;
}
$kid;
};
(_waitpid
サブ介して)これはwait_one_child
で行われることP::FM's source
から参照
上記で使用された0はこのメソッドの同義語です。
シグナルを受け取るメソッドwait_one_child
は、最大プロセス数が満たされ、1つが終了すると、子プロセスを収穫するために、start
によって使用されます。これは、モジュールがいつ他のプロセスを開始してその最大値を尊重することができるかをモジュールが知る方法です。 (プロセスを待ついくつかの他のルーチンでも使用されています。 )。 run_on_finish
がトリガされますとき、これは$s->on_finish($kid, ...)
sub on_finish {
my ($s,$pid,@par)[email protected]_;
my $code=$s->{on_finish}->{$pid} || $s->{on_finish}->{0} or return 0;
$code->($pid,@par);
};
コールバックは、それ自体がサブrun_on_finish
に設定されているオブジェクトのon_finish
キーから取得コードリファレンス$code
、であることで、あります。これがコールバックが設定される方法です。
このためにユーザに提供される方法は、wait_all_children
とreap_finished_children
です。
投稿コードにはこれが使用されていないため、$number_running
は更新されないため、while
は無限ループです。 の変数$number_running
は、子プロセスによって直接変更することはできません。
あなたはそのようなアイドルループで回転しないでください。あなたの親プロセスは、取得できるCPU時間をすべて使い切り、 '$ number_running'の値を無限にテストします。 – Borodin
'$ number_running'が子プロセスによってゼロに減少するまでどのように待つことができますか? – CJ7
@ CJ7子プロセスは、親プロセスで使用される '$ number_running'には影響を与えません。親プロセスは、互いの変数に書き込むことができません。親はこの変数を減分しなければなりません。私の答えに加えられた説明を見てください。 – zdim