PDA

Просмотр полной версии : Глобальные переменные и fork



wells
26.10.2004, 16:20
Есть глобальная переменная. Как из процесса-потомка, вызванного через fork, записать в неё какое-то значение? (Всё под Windows)

AiK
26.10.2004, 16:40
wells, не очень понятно, что есть в данном случае "глобальная переменная".

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

По этому микрософт не стал вводить аналог fork() в WinAPI и всех вынудил использовать трэды.

wells
26.10.2004, 16:56
To AiK: Глобальная переменная - это пременная объявленная в процессе родителе, до вызовf fork. Нужно её обработать после выполнения всех потомков.

AiK
26.10.2004, 17:55
wells, если я правильно понял, то waitpid тебе должен помочь.
Правда под виндой никогда не пробовал с fork работать.

wells
27.10.2004, 15: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
27.10.2004, 17: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
27.10.2004, 17: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
27.10.2004, 20: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
28.10.2004, 08:07
Это не прокатит, так как задержка это эмуляция работы достаточно длительного куска кода, который по результатам своей работы и пишет pipe! А через Thread нельзя ли это всё реализовать?

wells
28.10.2004, 12:41
Решил слепить тоже самое через Thread'ы.
Получается следующее:


use strict;
use Thread qw(async yield);
my $var = 0;
sub child {
{
lock $var;
if ($var == 0) {
yield;
$var++;
print "var is $var\n";
}
}
}
my $t2 = new Thread \&child;
$t2->join;
print "var is $var\n";


Почему в конце $var всё равно принимает старое значение?