2

aからeという名前の5つのファイルがあるとします。これらを並行して処理したいと思います。私はこのようなことをすることができると思いました:

my @ltrs = ('a'..'e');

for my $fnum (0..2) { 
    $pid = fork();
    if ($pid) {
        push(@childs, $pid);
    }
    elsif ($pid == 0) {
        do {
            my $ltr = shift(@ltrs);
            print "Open file $ltr on $fnum\n";
        } until (scalar(@ltrs)==0);
        exit(0);
    }
    else {
        die "Couldn't fork: $!\n";
    }
}

foreach (@childs) {
    waitpid($_, 0);
}

しかし、各子プロセスは次の5つの要素すべてにアクセスしています@ltrs

Open file a on 0
Open file b on 0
Open file c on 0
Open file d on 0
Open file e on 0
Open file a on 1
Open file b on 1
Open file c on 1
Open file d on 1
Open file e on 1
Open file a on 2
Open file b on 2
Open file c on 2
Open file d on 2
Open file e on 2

あるプロセスshiftが配列の要素である場合、次のプロセスが配列を調べるときにその要素がまだ存在するのはなぜですか?最初の後に、shift次に来るプロセスはすべて、で始まる配列を見つけるbと思いましたが、明らかに何かが欠けています。

4

2 に答える 2

7

データはプロセス間で共有されません。各プロセスには、その独自のコピーがあります。

共有したい場合は、プロセス間通信の全世界が開かれています。perldoc ページのperlipcは、それについてのすべてを教えてくれます。

インスタンスごとに完全なプロセスを必要としない場合は、スレッドを使用することも別の方法です。プロセスとは異なり、スレッドはデータを共有できます (ただし、Perl ではデフォルトで共有されません)。perldoc ページperlthrtutは、この特定のトピックの出発点です。

于 2012-11-21T16:32:28.843 に答える
3

これを試して:

use Parallel::ForkManager;

my $max_processes = 3;
my $pm = Parallel::ForkManager->new($max_processes);

my @ltrs = ('a'..'e');

for my $ltr (@ltrs) {
    my $pid = $pm->start and next;

    print "Open file $ltr in $$\n";
    sleep 1;
    $pm->finish;
}
$pm->wait_all_children;

これによりキューイングが処理され、一度に作業する子が 3 人を超えないようにします。ただし、コードとは異なり、文字ごとに個別のフォークを行います。

子から親にデータを返す必要がある場合は、https://metacpan.org/module/Parallel::ForkManager#Data-structure-retrieval に示すように run_on_finish フックを設定します

于 2012-11-21T19:39:48.593 に答える