Могу ли я использовать сигналы POSIX в моей программе Perl для создания событийно-ориентированного программирования? - PullRequest
5 голосов
/ 03 апреля 2010

Есть ли какие-либо сигналы POSIX, которые я мог бы использовать в моей программе Perl для создания событийно-ориентированного программирования? В настоящее время у меня есть многопроцессорная программа, которая может взаимодействовать друг с другом, но мой родительский поток может слушать только одного ребенка за раз.

foreach (@proc) {
  sysread(${$_}{'read'}, my $line, 100); #problem here
  chomp($line);
  print "Parent hears: $line\n";
}

Проблема в том, что родитель находится в состоянии постоянного ожидания, пока не получит сигнал от первого ребенка, прежде чем он сможет продолжить. Я полагаюсь на «трубу» для моего общения.

Мое текущее решение очень похоже на: Как я могу использовать `pipe` для облегчения межпроцессного взаимодействия в Perl?

Если возможно, я бы хотел положиться на событие $ SIG {...} или любое решение, не относящееся к CPAN.

Обновление:

Как упоминал Джонатан Леффлер, kill может использоваться для отправки сигнала:

убить USR1 => $$; # отправь себе SIGUSR1

Моим решением будет отправить сигнал USR1 моему дочернему процессу. Это событие говорит родителю слушать конкретного ребенка.

ребенок:

kill USR1 => $parentPID if($customEvent);
syswrite($parentPipe, $msg, $buffer);
#select $parentPipe; print $parentPipe $msg;

Родитель:

$SIG{USR1} = {
   #get child pid?
   sysread($array[$pid]{'childPipe'}, $msg, $buffer);   
};
  1. Но как мне получить мой исходный / дочерний pid, который сигнализировал родителю? Пусть ребенок идентифицирует себя в своем сообщении.
  2. Что произойдет, если двое детей подадут сигнал USR1 одновременно?

Обновление 2: решение

Я пошел с выбором, который использовал векторный подход для неблокирующего ввода-вывода. Для тех, кто сталкивается с этим потоком, проверьте: http://docstore.mik.ua/orelly/perl/cookbook/ch07_14.htm, поскольку он охватывает как векторный путь, так и модуль IO :: Select. Я понимаю, что модуль IO :: Select был бы более элегантным, но меня больше интересовало изучение новой механики Perl. Спасибо всем за помощь.

Оказывайте:

$rin = '';
# repeat next line for all filehandles to poll
vec($rin, fileno(FH1), 1) = 1;
vec($rin, fileno(FH2), 1) = 1;
vec($rin, fileno(FH3), 1) = 1;

$nfound = select($rout=$rin, undef, undef, 0);
if ($nfound) {
  # input waiting on one or more of those 3 filehandles
  if (vec($rout,fileno(FH1),1)) { 
      # do something with FH1
  }
  if (vec($rout,fileno(FH2),1)) {
      # do something with FH2
  }
  if (vec($rout,fileno(FH3),1)) {
      # do something with FH3
  }
}

Ответы [ 3 ]

9 голосов
/ 03 апреля 2010

Если вы хотите заниматься программированием на основе событий, взгляните на один из модулей событий CPAN, например POE , Coro или AnyEvent прежде чем изобретать свою вещь.

4 голосов
/ 03 апреля 2010

Вы можете использовать select для мониторинга каналов связи (примечание: если вы используете Win32, select может использоваться только в сокете).

Так что вы можете использовать такой код:

use IO::Select;
use IO::Handle;

...

$_->blocking(0) for @handles;

while( 1 ) {
    my $s = IO::Select->new( @handles );

    for my $h ( $s->can_read( 1 ) ) {

        my $data = read_handle($h);
        process_handle_data( $data );
    }

}

sub read_handle {
    my $h = shift;

    my $got = '';

    1 while read( $h, $got, 1024, length $got );

    return $got;
}

Посмотрите на пример UDP в perlipc. Он использует встроенный выбор. Я предпочитаю основной модуль IO::Select встроенному select, его гораздо легче читать.

Обновление: Вы действительно должны рассмотреть возможность использования инфраструктуры событий, такой как POE, Event или Coro. В этой ветке perlmonks есть довольно хороший список опций. Не бойся CPAN.

2 голосов
/ 03 апреля 2010

Чтобы ответить на прямой вопрос, SIGUSR1 и SIGUSR2 предназначены для «пользовательских» целей - чтобы вы могли их использовать.

Возможно, вам лучше взглянуть на уже существующую систему.

...