Forum Webscript.Ru

Программирование => Perl => Тема начата: AnnA от 09 Ноября 2004, 15:56:17

Название: ветвление процессов
Отправлено: AnnA от 09 Ноября 2004, 15:56:17
Всем приветик.
Умные дяденьки, помогите мне пожалуйста разобраться в этом лесу.
Ну никак что-то я не пойму, что там к чему.
Купила умную книжку, там расписано как использовать модуль Thread и всё бы хорошо, но он даже не установлен у меня такой на хостере к тому же хотелось бы научиться делать ЭТО сначала на fork. :)
Вот написано мол так и так, обязательно дескать используйте:#!/usr/bin/perl -Tw
    use strict;
    [b]use sigtrap;[/b]
    use Socket;
А мне и не жалко. Написано, значит так надо. Написала, делов-то. Только не совсем понятно - зачем? Куда его потом пихать этот $SIG{PIPE} = \'IGNORE\';?
Или я вообще что-то напутала?
Вот у меня есть, например, такая задача: нужно скажем с десяти разных адресов забрать модулем LWP по два-три документа (адреса и имена документов известны). В самом обычном текстовом файле лежат данные по строчкам: адрес, имя документа. Код не нужен - просто сама идея. :)
читаю я файл в массив(он небольшой - 10 строчек всего), а вот теперь самое для меня трудное, - как мне сделать несколько процессов. Т.е. по одному документику в цикле я получаю их все, но это очень уж долго. :(
Просто делаю for для массива, split\'ом достаю адрес, имя документа. Получила, следующий... Примитивно до обидного. :) Ой. Забыла. Сначала я пингую каждый адрес Net::Ping. Если есть пинг - забираю документ, пинга нет - next;
В общем идея такая:foreach (@massiv) {
my ($server,$port,$doca) = split... достаем данные

if ($pid = fork) {
 $p=ping->$server
   if ($p) { #пинг получен - сервер жив
             #запрашиваем $server:80/$doca при помощи LWP, делаем с ним чего-то;
           } #EO if($p)
             else {print $server,\'не отвечает\';}
waitpid($pid,0);
    } else {

        die "cannot fork: $!" unless defined $pid;
        exit;

    } #EO if ($pid = fork)

} #EO foreach (@massiv)
ужас, да? :(
Подскажите пожалуйста, как правильно а?
Целое письмо написала.  :)
Название: ветвление процессов
Отправлено: NeoNox от 09 Ноября 2004, 16:34:23
AnnA
1) пинг выносим за пределы форка. незачем нам форкаться а только потом проверять доступность.
2) прироста скорости ты не получишь, потому как в этой схеме ты будешь ждать завершения первого форка, затем второго и так далее.
Идея проста, но не очень красива: форкаться и отдавать управление внешнему(второму скрипту) через exec.
Цитировать
AnnA:
Куда его потом пихать этот $SIG{PIPE} = \'IGNORE\';?

С сигналами нужно вести очень осторожно и использовать их только тогда, когда понимаешь что они должны делать.
В данном случае его пихать никуда не нужно.
Название: ветвление процессов
Отправлено: AnnA от 09 Ноября 2004, 16:57:37
NeoNox пасиба большое. :)
Цитировать
NeoNox:
пинг выносим за пределы форка.

разве не будет быстрее, если будут пинговаться сразу несколько серверов, а не каждый по очереди?
я так и думала, что вся итерация foreach будет делиться скажем на 5 потоков, т.е. в идеале скрипт должен работать в 2 раза быстрее? нет? А как мне управлять количеством потоков? Где-то надо ставить счетчик, который, например, если ==5, то ждём завершения 1-го потока и вновь идём по кругу с 1-го по 5-й. Т.е. что бы их было не более 5. Или такое невозможно?
Цитировать
NeoNox:
Идея проста, но не очень красива: форкаться и отдавать управление внешнему(второму скрипту) через exec.

ага. :) поняла. спасибо.
А, если красиво (хотя бы просто красиво, а не очень пока) - надо всё таки через Thread делать?
Цитировать
NeoNox:
В данном случае его пихать никуда не нужно.
Хорошо. :) Я тут же забыла про эти сигналы. ;)
Название: ветвление процессов
Отправлено: NeoNox от 09 Ноября 2004, 18:22:18
Цитировать
AnnA:
надо всё таки через Thread делать?

Да. Это будет правильнее.
Цитировать
AnnA:
в идеале скрипт должен работать в 2 раза быстрее? нет?

в идеале да, но не в твоем случае.
напиши на бумажке что, как и когда у тебя происходит в этой программе.
выведи отладку вместе со временем исполнения и ты увидишь о чем я говорю.
Название: ветвление процессов
Отправлено: AnnA от 10 Ноября 2004, 15:19:41
:confused: Не работает. :insane:
тихохонько так раз. и умирает, и еррор.лог пустенький совершенно вот что обидно. :(
Может вы мне чего-то недоговариваете? :)
Поглядите, если не сложно:open(D,"<","$servers") or die "Can\'t read $servers: $!";
flock(D,LOCK_EX);seek(D,0,0);
while () {
my($server,$port)  = split(/:/,$_); chomp($port);
my $p = Net::Ping->new();
my $cont = $p->ping($server);
    $p->close();
    if ($cont)
{ print "$server is alive. \\t ";
#-------//BEGIN FORK//-------#
if ($pid = fork) {

#Здесь запросы с помощью LWP

waitpid($pid,0);
    } else {

        die "cannot fork: $!" unless defined $pid;
        exit;

    } #EO if ($pid = fork)
#-------//END FORK//-------#

###############################################
 }
    else {print "$server NOT reachible!
";}

    } #EO while
Название: ветвление процессов
Отправлено: AnnA от 10 Ноября 2004, 15:22:25
Цитировать
NeoNox:
выведи отладку вместе со временем исполнения

ух. это я не то что бы не умею --- я даже не знаю как это делать. Пока. До сих пор хватало лога...
Название: ветвление процессов
Отправлено: NeoNox от 10 Ноября 2004, 16:44:46
Вот тебе пример функции дебага.

вызываетсяя с любого доступного места как:

debug "I\'m here";

sub debug{

    my $now = localtime;
    my $data = join(\'\', @_);
    my $ra = $ENV{"REMOTE_ADDR"};

    my $msg = \'[%l] %s: %m (%d: - %h PID %p)\';
    my ($line, $subname) = (caller(1))[2,3];
    $msg =~ s/%l/$line/g;
    $msg =~ s/%s/$subname/g;
    $msg =~ s/%m/$data/g;
    $msg =~ s/%d/$now/g;
    $msg =~ s/%h/$ra/g;
    $msg =~ s/%p/$$/g;

    open (FH,">>", "./debug") or die "Can\'t open debug file: $!";
    print FH $msg."\\n";
    close FH;
}
Название: ветвление процессов
Отправлено: AnnA от 16 Ноября 2004, 13:12:48
вопрос не праздный. как ограничить рождаемость детей? ;)
(презервативы не предлагать) :)
серьезно - как? хотелось бы чтобы их было не более 5 одновременно.
Название: ветвление процессов
Отправлено: NeoNox от 16 Ноября 2004, 13:40:05
AnnA а подумать с карандашем в руке?
У тебя есть старт процесса и его конец? Вот и записывай +1 при старте процесса и отнимай при завершении.