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


Автор: GShadrin 1.12.2009, 17:15
Здравствуйте.
Столкнулся с необходимостью написания сервера, в котором для каждого подключившегося пользователя выделяется отдельный процесс. Воспользовался рецептом из кукбук 17.11
Код

Ответвляйте подпроцессы в цикле accept и используйте обработчик $SIG{CHLD} для чистки потомков. 
# Создать сокет SERVER, вызвать bind и прослушивать ... 
use POSIX qw(: sys_wait_h); 
sub REAPER { 
1 until (-1 == waitpid(-1, wnohang)); 
$SIG{CHLD} = \&reaper; # если $l >= 5.002 
} 
$SIG{CHLD} = \&reaper; 
while ($hisaddr = accept(client, server)) { 
next if $pid = fork; # Родитель 
die "fork: $!" unless defined $pid; # Неудача 
# otherwise child 
close(SERVER); # He нужно для потомка 
# ... Сделать что-то 
exit; # Выход из потомка 
} continue { 
close(CLIENT); # He нужно для родителя 
}


Вопрос:
Мне необходимо иметь некоторые данные общие для всех потоков. Как это сделать? При попытки объявления глобальной переменной $i и увеличении ее при каждом подключении нового пользователя с печатью номера вновь подключившегося пользователя привело к печати всегда 1, т.е. для каждого потока  $i свое. Похоже это связано с использованием fork. Как сделать общую?

Автор: Bulat 1.12.2009, 17:48
Цитата(GShadrin @  1.12.2009,  17:15 Найти цитируемый пост)
next if $pid = fork; # Родитель 


А зачем ты так жестко-то с родителем??

я так понял что тебе нужно контролировать количество потомков, тогда

Код

my $ChildCount = 0;
my $MaxChilds = 5;

#control and waiting signal from child process
$SIG{CHLD} = sub {while ( waitpid(-1, WNOHANG) > 0 ) { $ChildCount-- }}; 
...

while (1) {

  if ($ChildCount < $MaxChilds) { 
    ....
    $ChildCount++;

    my $pid = fork();

    unless ($pid) { 
      #потомок
      sleep(10);
    } else {
      #родитель
      #допустим print localtime, " : ", $ChildCount, "\n";
    }
  } else {
    sleep(5);
  }
}


Ну или просто как пример работы с форк... Писал "на коленке" мож есть необходимость в отладке.

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

Автор: GShadrin 1.12.2009, 18:32
Спасибо за ответ.
 
Цитата(Bulat @  1.12.2009,  17:48 Найти цитируемый пост)
А зачем ты так жестко-то с родителем??


Это взято из книги cookbook http://perl.find-info.ru/perl/015/socket/2.htm рецепт 17.11

Цитата(Bulat @  1.12.2009,  17:48 Найти цитируемый пост)
я так понял что тебе нужно контролировать количество потомков

Не совсем. Подсчет количества подключенных я приводил в качестве примера. Мне необходимо иметь именно переменные общие для всех процессов, с возможностью изменения их в любом процессе. Как я понял такое  невозможно.

Решил попробовать сделать на потоках theards используя эту же книгу.

Автор: Pfailed 1.12.2009, 18:57
Для связи процессов используйте каналы или разделяемую память.

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