Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Передача параметров в головной процесс


Автор: kukich 13.5.2011, 15:59
Здравствуйте,
Возникла задача :
Головной процесс в цикле создает определённое количество дочерних процессов(с помощью fork).
Каждый дочерний процесс берет информацию из массива ,обрабатывает и скидывает её головному процессу ,после чего умирает.А главный процесс создает еще один дочерний,который работает так же,как и предыдущий.
В нете куча примеров,как можно обеспечит обмен информацией 2 процесса - главный и дочерний(с помощью pipe).А вот если дочерних несколько,как организовать передачу данных?

Автор: arto 13.5.2011, 16:17
а что именно вызывает проблему?
заведение массива пайпов?

Автор: kukich 13.5.2011, 16:55
Ну вот я попытался организовать передачу данных через pipe для нескольких процессов:
Код

#!/usr/bin/perl
use IO::Handle;         # подключаем стандартный модуль
pipe(READER, WRITER);   # создаем программный канал
WRITER->autoflush(1);   # включаем авто-очистку буфера
$i;
$line;
$workers=10;
for ($i=1;$i<=$workers;$i++)
{
if ($pid = fork()) {    # процесс-предок получает PID потомка
   close WRITER;        # предок не писать в канал
   while (my $line = <READER>)
   {                    # чтение из приемника
      print "$line";
   }
   waitpid $pid, 0;     # ждем завершения потомка
   close READER;
}
else
{
   die "fork не отработал: $!" unless defined $pid;
   close READER;        # дочь не будет читать из канала
   $j=int(rand(10));
   print "Потомок $$ послал $j\n";
   print WRITER "$j\n";
   close WRITER;        # канал закрывается
   exit;                # потомок завершает работу
}
}

Потомок принимает сообщение от первого дочернего процесса , после чего reader закрывается.дальше потомки пишут впустую.В этом и вопрос - как сделать так,чтобы главный процесс принимал данные со всех дочерних процессов?

Автор: Pfailed 13.5.2011, 17:10
Скопировал из одного из проектов. Думаю смысл понятен.
Код

pipe(my $reader, my $writer);
    
for my $i (1..$workers) {
    $child = fork();
    unless(defined($child)) {
        Carp::carp("fork failed: ", $!);
        next;
    }
    elsif($child == 0) {
        close($reader);
        
        ...
        
        print $writer $sent, "\n";
        
        close($writer);
        exit();
    }
    
    $childs{$child} = undef;
}

close($writer);
my $sent = 0;

while(%childs) {
    my $pid = wait();
    $sent += <$reader>;
    delete $childs{$pid};
}

Автор: kukich 13.5.2011, 18:21
Спасибо большое, поковыряю скриптик!

Автор: kukich 16.5.2011, 16:55
Немного непонятно,зачем нужен хэш массив,не объясните?

Автор: Pfailed 16.5.2011, 18:34
В него складывается pid каждого из дочерних процессов, чтобы затем дождаться завершения каждого из них. Можно обойтись без хеша и воспользоваться обработчиком сигнала CHLD.

Добавлено через 9 минут и 10 секунд
Хотя можно и без CHLD, тем же wait, только считать количество завершенных процессов относительно количества запущенных. Получается хеш здесь действительно никчему.

Автор: kukich 18.5.2011, 17:01
Спасибо,всё стало ясно!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)