Главная страница


ru.perl

 
 - RU.PERL ----------------------------------------------------------------------
 From : vilfred                              2:5020/400     17 Jul 2003  19:16:08
 To : Edik Ryzhov
 Subject : Re: Многозадачность в эхотаге
 -------------------------------------------------------------------------------- 
 
 Привет!!
 
 ER> Стоит задача написать что-то вpоде демона, по таймеpy/pасписанию 
 
 запyскающемy
 
 ER> опpеделенные пpогpаммки и обpабатывающемy их коды возвpата. 
 
 Посколькy
 
 ER> пpогpаммки могyт выполняться довольно долго, хочется pеализовать 
 
 сабж, чтобы
 
 ER> шедyлеp/демон не висел в ожидании окончания одной пpогpаммы, а 
 
 запyскал сpазy
 
 ER> несколько. Сижy yже 8 часов - кypю perlfunc,perlipc,perlthrtut и 
 
 ничего не
 
 ER> полyчается =( 
 
 Возьмите книжку "Perl Библиотека программиста"... вообще, имхо, 
 достаточно этой книги и perldoc perlipc
 
 Вам надо посадить демона, который бы сам эмулировал кронтаб. По 
 запусканию определенной проги он бы форкал процесс, который 
 контролировал бы вывод этой проги. Потому как если с кронтабом 
 работать, надо будет кронтабом запускать определенннеую прогу, которая 
 бы звонила к перловому демону, а это неудобно...
 
 И еще, в перле как нигде удобно работать с отфорканными процессами, 
 открывать дексрипторы(пайпы, каналы, трубы - кому как нравится, короче 
 IPC) между процессами, вводить общие на 2, 3, ... n процессов 
 переменные и так далее...  эхотаг это не язык, а вообще какой-то 
 гипермегасупер... 
 
 ER> Что откpывать дочеpний пpоцесс чеpез _fork_, что чеpез
 ER> _open(F,"-|");_ не выходит, пpиходиться ждать STDIN. С сигналами 
 
 тоже не могy
 
 ER> pазобpаться. В perlthrtut что-то написано пpо экспеpиментальный 
 
 модyль Thread,
 
 ER> только его почемy-то нет в моей инсталляции, хотя в perlmodlib он 
 
 описан как
 
 ER> стандаpтный.
 
 ER> Вообщем, товаpищи/господа, помогите добpым советом, кyском кода или 
 
 посыланием
 
 ER> на CPAN, хотя последнее лyчше не надо, хоpошо бы только стандаpтное 
 
 юзать.
 
 есть прога, которая долбится через сокет на определнный порт, в случае 
 неудачи чайлд перезапускается, в случае удачи чайд форкается на сервер 
 и клиент, клиент подсоединяется к той самой проге, а сервер принимет и 
 транслирует ответы от клиентов, работающих с упомянутой прогой. Итого, 
 один парент генерит чайлдов, которые в случае подключения сами форкают 
 чайлдов. А все отчего, один мужик написал прогу, которая часто падает, 
 и, к тому-же, к этой проге по сокету можно подконнектится только два 
 раза. А надо любое число раз и пришлось писать обвязку:
 
 ========begin=======
 #!/usr/bin/perl -w
 
 use strict;
 use IO::Socket;
 use IO::Handle;
 use Socket;
 use Symbol;
 use POSIX;
 use Net::hostent;
 
 my $port=6001; 
 my $host="127.0.0.1"; 
 my $PREFORK="1"; 
 my $MAX_CLIENTS_PER_CHILD="1";
 my %children=(); 
 my $children=0;
 my $f="/.2/mnt/work/control.txt";
 make_new_child() for(1 .. $PREFORK);
 
 $SIG{CHLD}=\&REAPER; 
 $SIG{INT}=\&HUNTSMAN;
 
 while(1){ 
   sleep; 
   for(my $i=$children; $i<$PREFORK; $i++){
     make_new_child()
   }
 }
 
 sub make_new_child{ 
   my($pid, $sigset, $kidpid, $server, $client);
 
   $sigset=POSIX::SigSet->new(SIGINT);
   sigprocmask(SIG_BLOCK, $sigset) or die "can't block SIGINT for fork: 
 $!\n";
   die "fork: $!" unless defined do{$pid = fork};
 
   if($pid){
 
     sigprocmask(SIG_UNBLOCK, $sigset) 
       or die "can't unblock SIGINT for fork: $!\n";
 
     $children{$pid}=1; 
     $children++; 
     return;
   } else {
     $SIG{INT} = 'DEFAULT'; 
     $SIG{CHLD}='IGNORE';
 
     sigprocmask(SIG_UNBLOCK, $sigset) 
       or die "can't unblock SIGINT for fork: $!\n";
 
     for(my $i=0;  $i<$MAX_CLIENTS_PER_CHILD; $i++){ 
       sleep 2;
 
       socketpair(CHILD, PARENT, AF_UNIX, SOCK_STREAM, PF_UNSPEC) 
   or die "socketpair: $!";
       #открываем двусторонний обмен данными между чайлдом и парентом
       CHILD->autoflush(1); 
       PARENT->autoflush(1);
       #отключаем буферизацию
       my $handle = IO::Socket::INET->new( Proto    => 'tcp',
             PeerAddr => $host,
             PeerPort => $port) 
   or die "can't connect to port $port on $host: $!";
       #поднимаем клиента
       print STDERR "[Connected to $host:$port]\n";
       die "can't fork: $!" unless defined do{$kidpid = fork()};
       
       if ($kidpid) { 
   #парент, все что в этом условии работает только для парента
   my ($byte, $tmp); 
   close PARENT;
   #так как парент, закрываем дескриптор парента
   while(sysread($handle, $byte, 1) eq 1){ 
      #посимвольно читаем из сокетной проги
     $tmp.=$byte;
     do{print CHILD "$tmp\n"; 
       #пишем в чайлд либо ok либо error
       $tmp=''
     } if $tmp eq 'ok';
     do{print CHILD $tmp,"\n"; $tmp=''} if $tmp eq 'error';
   } 
   close CHILD;
   kill "TERM" => $kidpid; #убиваем
   waitpid($kidpid,0);  #отслеживаем зомби
       } else { 
   #тут начинается чайлд
   close CHILD; 
   $server = IO::Socket::INET->new( LocalPort => 2003,
            Type      => SOCK_STREAM, 
            Proto     => 'tcp',
            Reuse     => 1,
            Listen    => 10); 
   die "making socket: $@" unless $server;
   #поднимаем сервер, транслирующий ответы проги, к которой
   #коннектятсячерез сокет, фишка в том, что 
   #та прога отрабатывает только два подключения
   #а надо любое число, вот клиенты и коннектятся к серваку
   #любое число раз, а обмен данными происходит через
   #двусторонний сокет между парентом и чайлдом
   while($client=$server->accept()){
     $client->autoflush(1);
     my ($line, $line1);
     while (defined ($line = <$client>)){
       print $handle $line;
       #пишем в клиента, который работает с прогой команду
       chomp($line1=<PARENT>);
       #читаем из чайлда ответ
       print $client "$line1\n";
       #пишем подконнектившемуся по сокету юзеру ответ проги
     } 
     close $client;
   } 
   close PARENT;
       } 
     } exit;
   }
 }
 
 sub HUNTSMAN{
   #отрабатываем перезапуски...
   local($SIG{CHLD})='IGNORE';
   kill 'INT' => keys %children;
   exit;
 }
 
 sub REAPER{
   #убиваем чайлда по сигналу...
   $SIG{CHLD}=\&REAPER;
   my $pid = wait;
   $children--;
   delete $children{$pid};
 }
 
 =========end========
 
 ваще когда написал - охренел, _насколько_ просто и _что_ можно перлом 
 сделать... правда втыкал в перловые межпроцессные взаимодействия не 
 торопять, полгода где-то... а первую прогу с IPC, которая отслеживала 
 падение интернета через GPRS сотового телефона полтора месяца вообще 
 писал... зато как связь в beeline падает(пинг пропадает, route 
 прежний), гудит гудок, по которому надо нажимать на кнопку на 
 телефоне... осталось купить телефон у которого нормальный 
 вход есть, тогда вообще автоматически самоподдерживаемая 
 связь будет, а пока, увы, работаем через инфракрасный порт. 
 
 ER> ЗЫ. perl v5.6.1
 
 такаяже шняга, хоят то чел, чья прога, писал ваще под дос...
 
 Дима
 -- 
 TEAM [Маньяки]
 Отправлено через сервер Форумы@mail.ru - http://talk.mail.ru
 --- ifmail v.2.15dev5
  * Origin: Talk.ru (2:5020/400)
 
 

Вернуться к списку тем, сортированных по: возрастание даты  уменьшение даты  тема  автор 

 Тема:    Автор:    Дата:  
 Многозадачность в эхотаге   Edik Ryzhov   17 Jul 2003 00:04:26 
 Re: Многозадачность в эхотаге   Igor S Chencov   17 Jul 2003 11:36:50 
 Re: Многозадачность в эхотаге   vilfred   17 Jul 2003 19:16:08 
 Многозадачность в эхотаге   Denis Knyazev   17 Jul 2003 16:51:15 
 Re: Многозадачность в эхотаге   Artem Chuprina   01 Aug 2003 15:07:44 
 Re: Многозадачность в эхотаге   Alexander Orlovsky   01 Aug 2003 15:45:37 
 Re: Многозадачность в эхотаге   Artem Chuprina   04 Aug 2003 11:00:45 
Архивное /ru.perl/64889f30559f.html, оценка 2 из 5, голосов 10
Яндекс.Метрика
Valid HTML 4.01 Transitional