Perl разветвляет процесс внутри оператора if выполняет оба блока - PullRequest
1 голос
/ 11 июля 2019

Когда я запускаю новый процесс внутри условия if, неожиданно выполняются оба блока if и else.
Согласно документации подпрограммы perl fork, когда мы выполняем метод, он возвращает либо undef, PID в зависимости от того, произошел ли сбой форка, соответственно, успешно.

Ниже приведен код выполнения обоих блоков.

if(my $a = fork ) {
  say "if block"; 
} else {
  say "else block";
}

выход:
если блок
еще блок

Где, как будто я возвращаю их вручную, выполняется только один блок в зависимости от того, верну я 0 или 1.

sub a { 1; }

if(my $a = a ) { 
  say "if block"; 
} else {
  say "else block";
}

выход:
если блок

Есть идеи, почему это происходит?

Ответы [ 2 ]

4 голосов
/ 11 июля 2019

В соответствии с документацией подпрограммы perl fork, когда мы выполняем метод, он возвращает либо undef, PID в зависимости от того, произошел ли сбой форка, либо, соответственно, успешно.

Не совсем.Фактически он говорит следующее:

Возвращает дочерний pid родительскому процессу, 0 дочернему процессу или undef, если ответвление не выполнено.

Итак,

  • В родительском процессе fork возвращает PID дочернего процесса, поэтому родительский процесс выводит if block.
  • Вдочерний процесс, fork возвращает 0, поэтому дочерний процесс выводит else block.

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

2 голосов
/ 11 июля 2019

Проще увидеть, что происходит, если вы также выводите идентификатор процесса (специальную переменную $$) с каждым оператором say:

use v5.10;

if( fork ) {
  say "$$ (parent): if block";
} else {
  say "$$ (child): else block";
}

Затем вы увидите, что вы получаете выходные данные издва разных процесса:

19997 (parent): if block
20024 (child): else block

Как правило, родительский процесс продолжается и делает свое дело, в то время как дочерний процесс продолжает и выполняет любую работу, которую вы хотели разгрузить.Однако дочерний объект наследует стандартные файловые дескрипторы родительского элемента, поэтому выходные данные отправляются в то же место.Если вы этого не хотите, вы можете немедленно изменить стандартный вывод (и другие) в дочернем (или, я думаю, родительском):

use v5.10;

if( fork ) {
  say "$$ (parent): if block";
} else {
  say "$$ (child): else block";
  open STDOUT, ...
}

Если вы хотите, чтобы текущий процесс превратился во что-то другое (чтобы у вас все еще был только один процесс), посмотрите на exec .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...