Глобальные переменные и fork

Обсуждение серверного программирования.

Модераторы: Duncon, Yurich

wells
Сообщения: 19
Зарегистрирован: 27 сен 2004, 12:31
Откуда: Москва

26 окт 2004, 17:20

Есть глобальная переменная. Как из процесса-потомка, вызванного через fork, записать в неё какое-то значение? (Всё под Windows)
Аватара пользователя
AiK
Сообщения: 2271
Зарегистрирован: 13 фев 2004, 18:14
Откуда: СПб
Контактная информация:

26 окт 2004, 17:40

wells, не очень понятно, что есть в данном случае "глобальная переменная".
Даже самый дурацкий замысел можно воплотить мастерски
Absurd
Сообщения: 1213
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

26 окт 2004, 17:48

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

По этому микрософт не стал вводить аналог fork() в WinAPI и всех вынудил использовать трэды.
2B OR NOT(2B) = FF
wells
Сообщения: 19
Зарегистрирован: 27 сен 2004, 12:31
Откуда: Москва

26 окт 2004, 17:56

To AiK: Глобальная переменная - это пременная объявленная в процессе родителе, до вызовf fork. Нужно её обработать после выполнения всех потомков.
Аватара пользователя
AiK
Сообщения: 2271
Зарегистрирован: 13 фев 2004, 18:14
Откуда: СПб
Контактная информация:

26 окт 2004, 18:55

wells, если я правильно понял, то waitpid тебе должен помочь.
Правда под виндой никогда не пробовал с fork работать.
Даже самый дурацкий замысел можно воплотить мастерски
wells
Сообщения: 19
Зарегистрирован: 27 сен 2004, 12:31
Откуда: Москва

27 окт 2004, 16:37

Есть такой код:

Код: Выделить всё

use IO::Handle; 
use strict; 
my $threads = 5;
pipe(READER, WRITER); 
autoflush WRITER; 
my ($pid,  $line);
my $threads = 5;
for (my $i = 1; $i <= ($threads); $i++) {
	if ($pid = fork) { 
    	close WRITER; 
    	chomp($line = <READER> ); 
    	#print $line; 
    	close READER; 
    	waitpid($pid,0); 
	} 
	else { 
    	die "cannot fork: $!" unless defined $pid; 
    	close READER; 
    	print WRITER "4"; #This value will be sent to $line 
    	close WRITER;  # this will happen anyway 
    	exit; 
	}
}
print $line;

Так вот если $threads = 1, всё работает. А при другом значении, например 5, нет!
chur
Сообщения: 195
Зарегистрирован: 17 фев 2004, 10:44
Откуда: Riga, Latvia

27 окт 2004, 18:14

Перенеси pipe(READER, WRITER) в цикл.

Код: Выделить всё

use IO::Handle; 
use strict; 
#my $threads = 5; 
autoflush WRITER; 
my ($pid,  $line); 
my $threads = 5; 
for (my $i = 1; $i <= ($threads); $i++) { 
   pipe(READER, WRITER); 
   if ($pid = fork) { 
       close WRITER; 
       chomp($line = <READER> ); 
       #print $line; 
       close READER; 
       waitpid($pid,0); 
   } 
   else { 
       die "cannot fork: $!" unless defined $pid; 
       close READER; 
       print WRITER "4"; #This value will be sent to $line 
       close WRITER;  # this will happen anyway 
       exit; 
   } 
} 
print $line; 
wells
Сообщения: 19
Зарегистрирован: 27 сен 2004, 12:31
Откуда: Москва

27 окт 2004, 18:53

В том то и вопрос, что если в процессе потомке что-то делать, то распаралеливание процессов не получается. Например если в ветку else засунуть

Код: Выделить всё

my $i = 0;
for ($i; $i<=10 ; $i++) {
   Time::HiRes::sleep(1.0);
}
то весь скрипт выполняется в пять раз дольше!!!
Вообщем есть следующий скрипт:

Код: Выделить всё

use strict;
use IO::Handle;
use Benchmark;
my $tmStamp1 = new Benchmark;
#/////////////////////////////////////////////////////////////////////////////////
my $threads = 5;
my @pids;
my $isExit = 0;
#/////////////////////////////////////////////////////////////////////////////////
print "$isExit\n";
print "start\n";
for (my $i = 1; $i <= ($threads); $i++) {
	pipe(PARENT_RD, CHILD_WR); 
	autoflush CHILD_WR;
	my $pid;
	if ($pid = fork) {
		close CHILD_WR; 
		chomp($isExit = <PARENT_RD>); 
		close PARENT_RD;
		push(@pids,$pid);
	}
	else {
		die "cannot fork: $!" unless defined $pid;
		my $i = 0;
		for ($i; $i<=5; $i++) {
			Time::HiRes::sleep(1.0);
		}
	    close PARENT_RD;
	    print CHILD_WR "1"; 
    	close CHILD_WR; 
		exit;
	}
}
for (my $l = 0; $l <= ($threads-1); $l++) {
	print "$pids[$l]\n";
	waitpid($pids[$l], 0);
}
print "stop\n";
print "$isExit\n";
#/////////////////////////////////////////////////////////////////////////////////
my $tmStamp2 = new Benchmark;
my $tmDiffer = timediff($tmStamp1, $tmStamp2);
print timestr($tmDiffer);
Так вот при $threads = 1 он выполняется 6 секунд, а при = 5, скрипт работает все 30 секунд.
Получается, что процессы-потомки работают последовательно.
Если убрать всё, что связанно с pipe при любом значении $threads ( вплоть до 50)
скрипт выполняется за теже 6 секунд.
Вот в чём собака порылась!
chur
Сообщения: 195
Зарегистрирован: 17 фев 2004, 10:44
Откуда: Riga, Latvia

27 окт 2004, 21:57

В этом месте

Код: Выделить всё

chomp($isExit = <PARENT_RD>);
родительский процесс ждет пока ты ему чего-нибудь напишешь и дальше не выполняется. Поставь цикл задержки после отправки сообщения, и все будет выполняться 6 секунд

Код: Выделить всё

   else { 
      die "cannot fork: $!" unless defined $pid; 
       close PARENT_RD; 
       print CHILD_WR "1"; 
       close CHILD_WR; 
      my $i = 0; 
      for ($i; $i<=5; $i++) { 
         Time::HiRes::sleep(1.0); 
      } 
      exit; 
   } 
wells
Сообщения: 19
Зарегистрирован: 27 сен 2004, 12:31
Откуда: Москва

28 окт 2004, 09:07

Это не прокатит, так как задержка это эмуляция работы достаточно длительного куска кода, который по результатам своей работы и пишет pipe! А через Thread нельзя ли это всё реализовать?
Ответить