Perl IPC без использования общей памяти? - PullRequest
2 голосов
/ 07 января 2012

Часть кода:

sub _getPages {
    my $self      = shift;
    my $rel_url   = lc(shift);
    my @turls     = ();
    my $urls      = [];
    my $ipc_share =  tie $urls, 'IPC::Shareable',undef, { destroy   => 1 };

    foreach my $stag (@{$self->{SUPP_TAGS}}) {

           push(@{$urls}, map { lc($self->_normalizeSupportURL($_->url(),
                                                             $self->{MECH_O}->getGlobalMechInstance()->uri->authority,
                                                             $self->{MECH_O}->getGlobalMechInstance()->uri->scheme)) }
                              grep { ((index($_->url,$rel_url) > -1) || ($_->url =~ m{^/})) &&
                                     $_->url !~ m/answer|mailto:/i }
                        $self->{MECH_O}->getGlobalMechInstance()->find_all_links( text_regex     => qr/$stag/i ),
                        $self->{MECH_O}->getGlobalMechInstance()->find_all_links( name_regex     => qr/$stag/i ),
                        $self->{MECH_O}->getGlobalMechInstance()->find_all_links( url_abs_regex  => qr/$stag/i ));
    }
    @{$urls} = uniq(@{$urls});

    foreach my $url (@{$urls}) {

        if (!exists($self->{UNQ_URLS}->{lc($url)}))  {
            $self->{UNQ_URLS}->{lc($url)} = 1;

            $self->{SUPP_PROC}->start and next;
            if (eval {$self->{MECH_O}->getGlobalMechInstance()->get($url); } ) {
                push(@{$urls}, map { lc($self->_normalizeSupportURL($_->url(),
                                                                  $self->{MECH_O}->getGlobalMechInstance()->uri->authority,
                                                                  $self->{MECH_O}->getGlobalMechInstance()->uri->scheme)) }
                             grep { ((index($_->url,$rel_url) > -1) || ($_->url =~ m{^/}) ||
                                      $_->url =~ m/\d+\.\d+\.\d+\.\d+/ ) &&
                                      $_->url !~ m/answer|mailto:/i }
                             $self->{MECH_O}->getGlobalMechInstance()->find_all_links( text_regex     => qr/chat/i ),
                             $self->{MECH_O}->getGlobalMechInstance()->find_all_links( name_regex     => qr/chat/i ),
                             $self->{MECH_O}->getGlobalMechInstance()->find_all_links( url_abs_regex  => qr/chat/i ));
            }
            $self->{SUPP_PROC}->finish;
        }
    }
    $self->{SUPP_PROC}->wait_all_children;

    return uniq(@{$urls});
}

По сути, я пытаюсь разделить $urls между процессами, чтобы я мог добавить к нему URL-адреса, но я продолжаю получать:

Не удалось создать набор семафоров: на устройстве не осталось места

, что необходимо для параметров ядра (Ubuntu 10.04 LTS) (SEMMNI, SEMMNS).Я увеличил их, но это все еще не очень полезно, так что я, вероятно, что-то здесь не так делаю.

Есть ли другой способ (вероятно, Storable связанное решение ...) для разделения массива между процессами?

Спасибо

1 Ответ

4 голосов
/ 07 января 2012

Возможно, вы уже сделали это, но всегда полезно точно подтвердить, что не работает и вступили ли изменения в силу.Чтобы подтвердить, что это действительно semget (), возвращающий ENOSPC, вы можете запустить его с:

strace -ooutfile CMD

, а затем найти ENOSPC в outfile, чтобы подтвердить, какой системный вызов вернул его.

Чтобы подтвердить настройку SEMMNI и SEMMNS, вы можете:

cat /proc/sys/kernel/sem

(как говорит man proc , SEMMNI - четвертое поле,SEMMNS - это второе поле).


Теперь, чтобы ответить на ваш вопрос "что еще я мог бы использовать?"непосредственно, вот несколько вариантов:

  • Мой первый выбор: использовать темы.Вы не показываете код, который запускает другие процессы, но так как вы разделяете массив Perl между ними, я подозреваю, что все процессы работают на одном и том же скрипте Perl (или код может быть написан таким образом).Поэтому вместо разветвления процессов используйте threads и используйте примитивы блокировки потоков, чтобы разделить массив @urls между потоками.Я говорю, что это мой первый выбор, потому что многопоточность чаще делается с потоками, чем с разветвлением в наши дни, поэтому есть много хороших примеров, и доступные модули имеют много использования (и они обычно не зависят от Sys Vинтерфейсы).

  • Мой второй вариант - использовать File :: Map для обмена данными между процессами.Опять же, это позволяет избежать интерфейсов Sys V и, вероятно, на каждый бит быстрее, чем разделяемая память, поскольку система, конечно, будет кэшировать страницы общего файла в ОЗУ (вы даже можете попросить систему закрепить файл в ОЗУесли хочешь).Как и в комментариях к темам выше, не забудьте использовать соответствующую блокировку.

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

Надеюсь, что это даст вам несколько жизнеспособных альтернатив.

...