perl 在 if 语句中分叉进程执行两个块

perl forking the process inside the if statement executes both the blocks

当我在 if 条件下分叉一个新进程时,令人惊讶的是 ifelse 块都被执行了。
根据执行该方法时perl fork 子例程文档,它return 是undefPID 取决于fork 是否失败,分别是成功。

下面是执行两个块的代码。

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

output:
if block
else block

好像我 return 那些手动只执行一个块取决于我 return 0 还是 1。

sub a { 1; }

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

output:
if block

知道为什么会这样吗?

According to the perl fork subroutine documentation when we execute the method, it returns either undef, PID depending on whether the fork failed, succeeded respectively.

不完全是。它实际上是这样说的:

It returns the child pid to the parent process, 0 to the child process, or undef if the fork is unsuccessful.

所以,

  • 在父进程中,fork returns子进程的PID,所以父进程输出if block.
  • 在子进程中,forkreturns0,所以子进程输出else block.

通过检查返回值,您可以让父子做不同的事情。

如果您还为每个 say 语句输出进程 ID($$ 特殊变量),则更容易看出发生了什么:

use v5.10;

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

然后您会看到您从两个不同的进程获得输出:

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

通常,parent 进程会继续执行它的任务,而 child 进程会继续执行您想要卸载的任何工作。然而,child 继承了 parent 的标准文件句柄,所以输出到同一个地方。如果你不想这样,你可以立即更改 child(或 parent,我猜)中的标准输出(和其他输出):

use v5.10;

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

如果您希望当前进程变成其他进程(这样您仍然只有一个进程),请查看exec