Разветвите нескольких детей в Perl и используйте каналы для двунаправленного общения - PullRequest
4 голосов
/ 08 декабря 2011

Я пытаюсь создать небольшую программу на Perl, которая имеет несколько возможностей обработки. Поскольку в моих требованиях есть кое-какие небольшие изменения, я нигде не могу найти подобные примеры сценариев.

Мне нужно прочитать большой лог-файл из STDIN и дать первое N число (опять большое число) строк первому дочернему процессу, а затем следующее N строк для второго дочернего процесса и т.д. это максимальное количество дочерних процессов, разрешенных для одновременного запуска. Как только будет достигнуто максимальное количество детей, родитель будет ждать, пока ребенок закончит свою работу, и предоставит ему еще N строк.

Родительский процесс также собирает многострочный (5-10 строк) вывод, возвращаемый каждым дочерним процессом по завершении, и сохраняет его в массиве. Затем родительский объект продолжает обрабатывать содержимое этого массива и, наконец, отображать результаты.

Есть ли лучший пример сценария, который я могу изменить и использовать, или кто-то может мне помочь, поделившись им здесь? Я предпочитаю использовать только каналы для взаимодействия процессов и максимально упростить процесс.

Edit: Может кто-нибудь показать пример того, как это можно сделать только с помощью каналов из модуля IO :: Handle?

Ответы [ 2 ]

5 голосов
/ 08 декабря 2011

Используйте 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 голосов
/ 08 декабря 2011

Я обнаружил, что потоки намного проще для такого рода процессов.Вам нужны модули Threads и Threads :: Queue.Процесс состоит в том, чтобы настроить очередь для подачи рабочих потоков и одну для них, чтобы они возвращали свои результаты.Рабочий поток - это просто функция для чтения записи, ее обработки и отправки результата обратно.Я просто собрал этот код и не тестировал его, поэтому он может содержать ошибки, но я думаю, что он показывает общую идею:

...