Forum Webscript.Ru
Программирование => Perl => Тема начата: Wells от 26 Октября 2004, 17:17:29
-
Есть глобальная переменная. Как из процесса-потомка, вызванного через fork, записать в неё какое-то значение? (Всё под Windows)
-
А в чем загвоздка?
-
Есть следующий код:
use strict;
use Benchmark;
my $tmStamp1 = new Benchmark;
#/////////////////////////////////////////////////////////////////////////////////
$| = 1;
my $threads = 5;
my @pids;
my $isExit = 0;
#/////////////////////////////////////////////////////////////////////////////////
for (1 .. $threads) {
makeChild();
}
print "$isExit\\n";
for (my $i = 0; $i <= ($threads-1); $i++) {
print "$pids[$i]\\n";
waitpid($pids[$i], 0);
}
print "$isExit\\n";
#/////////////////////////////////////////////////////////////////////////////////
my $tmStamp2 = new Benchmark;
my $tmDiffer = timediff($tmStamp1, $tmStamp2);
print timestr($tmDiffer);
#/////////////////////////////////////////////////////////////////////////////////
sub makeChild {
my $pid;
die "fork: $!" unless defined ($pid = fork);
if ($pid) {
push(@pids,$pid);
return;
}
else {
my $i = 0;
for ($i; $i<=10 ; $i++) {
Time::HiRes::sleep(1.0);
}
$isExit = 1;
exit(0);
}
}
#/////////////////////////////////////////////////////////////////////////////////
Так вот $isExit не меняется перед выходом из скрипта
-
Wells а с какой радости он должен меняться?
Вместо того что-бы вываливать кучу ненужного кода разобрался бы в сабе с fork.
-
Вот тебе для внекласного чтения:
use IO::Handle;
use strict;
my ($line, $pid);
autoflush STDOUT;
if ($pid = open(CHILD, "-|")) {
chomp($line = );
print $line;
close(CHILD);
} else {
die "cannot fork: $!" unless defined $pid;
print STDOUT "4"; #This value will be sent to $line
exit;
}
-
Если бы я сам мог разобраться - сюда не писал бы!!!!
To NeoNox: твой код выдаёт:
\'-\' is not recognized as an internal or external command,
operable program or batch file.
P.S. И какой это я "ненужный" код "вывалил"? Я "вывалил" свой скрипт! И всё!
-
perldoc perlipc
-
Wells
Wells:
И какой это я "ненужный" код "вывалил"?
У тебя непонимание принципа fork.
Строки c 1 по 23 не имеют к твоей проблеме ни малейшего отношения.
Читать
perldoc -f fork
perldoc perlipc
до того как применять мое решение.
Wells:
To NeoNox: твой код выдаёт:
Да, я не учел что ты под виндовсом.
Вот исправленный вариант:
use IO::Handle;
use strict;
pipe(READER, WRITER);
autoflush WRITER;
my ($pid, $line);
if ($pid = fork) {
close WRITER;
chomp($line = );
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;
}
-
To NeoNox: Всё работает! Спасибо! Только я вот не зря весь кусок кода вывалил. У меня там есть цикл, в котором 5 раз вызываются потомки. Так вот, как в конце проверить записал потомок что-то или нет? С одним потомком всё работает! А как с пятью быть???
-
Ну так напиши, в чем проблема?
Или мне все за тебя написать?
-
To NeoNox: Я понимаю - ты профи и для тебя это туфта, но у меня ничерта не получается! Вот так не работает:
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 = );
#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;
-
Лень это хорошо, но понимание сути вопроса - еще лучше.
Перенеси
pipe(READER, WRITER);
autoflush WRITER;
внутрь цикла.
-
В том то и вопрос, что если в процессе потомке что-то делать, то распаралеливание процессов не получается. Например если в ветку else засунуть
my $i = 0;
for ($i; $i<=10 ; $i++) {
Time::HiRes::sleep(1.0);
}
то весь скрипт выполняется в пять раз дольше!!!
-
Wells правильно. а ты что хотел от так написанной программы?
Напиши на бумаге логику что должно произойти, а потом напиши это на Perl. Будут вопросы, сначала полностью логику сюда, а потом будем разбираться дальше.
-
1. читаем вдумчиво perldoc -f fork
2. пишем комментарий к каждой строчке в твоей программе
-
Смысл в следующем:
Пишу сетевой сканер для служебных целей.
Сканируемая сеть около 10000 узлов.
С одним потоком сканирование занимает более 3 часов.
Нужно ускорить этот процес. Решил разбить на 5 потоков (через fork). Процесс ускорился до 45 минут. Но встали проблемы с оповещением.
Алгоритм примерно следующий:
1 - $isAlert = 0;
2 - создание массивов из IP адресов, по количеству потоков сканирования;
4 - создание потоков сканирования (через fork);
5 - для каждого адреса выполняется определённая проверка. Если условие выполняется, то переходим к следующему адресу. Если нет, то нужно $isAlert присвоить 1;
6 - ожидаем окончания работы всех потоков;
7 - формируем лог;
8 - если $isAlert = 1 отправляем лог по почте админу.
9 - выход.
Всё работает. Не могу побороть только пункт 8. Точнее с 1 потоком никаких проблем нет. А больше не идёт!
P.S. PERL\'ом я занялся месяц назад. Так что жду снисхождения.
-
Решил слепить тоже самое через 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 всё равно принимает старое значение?
-
Если уж ты на тредах решил делать (на мой взгляд это правильно) взгляни http://www.unix.org.ua/orelly/perl/prog3/ch17_02.htm
На пример 17.2.2.3. Locking subroutines