Perl,如何从 exec、system、win32 和 Unix 上的打开函数中获取线程的 pid



这个问题并不新鲜,https://www.perlmonks.org/?node_id=620645,但我没有找到我的问题的有效答案。简而言之,我想访问由系统、可执行文件或打开等函数创建的线程/进程的 PID。我使用打开函数my $pid = open my $fhOut, "| the command ", or die ...;发现的一个,在 Linux 中,根据ps命令的实际 PID 值是$pid + 2,但在 wind32 中,实际的 PID 是一个负数(如 -1284(。在这两种情况下,打开函数返回的 PID 都与 $pid 不同!!

同样,my $pid = system 1, "command params"返回的 pid 与操作系统中的 PID 不匹配。有人可以解释一下吗?退出从开放或系统函数调用的无限循环程序的正确方法是什么? 这是我的测试代码:

my $pid = fork();
if( $pid == 0 ) 
{
my $mimperf_pid = open my $cmd, "mimperf -C  $db > results/mimperf/mimperf.log |" or die $!;
sleep(10);
print $mimperf_pid;
kill 'KILL', $mimperf_pid; 
exit 0;
}

在此代码中,我试图杀死通过open函数创建的线程($mimperf_pid(,但没有成功。

Windows不支持fork(),所以Perl(很差(使用线程模拟它。这些虚拟进程具有负 PID。如果可以的话,你应该避免在Windows上fork(),如果没有别的,就使用线程。

不过,这与你的问题无关。虽然fork返回的 PID 为负数,但open返回的 PID 不是负数。


一般应避免两参数open,所以

open my $cmd, "foo bar |"

相当于

open my $cmd, "-|", "foo bar"

这相当于

open my $cmd, "-|", "cmd", "/x", "/c", "foo bar"

您正在启动一个 shell 来执行 shell 命令,open返回的是 shell 的 PID。

system 1, $shell_cmd也是如此。

这意味着 Ctrl-Break 信号正在发送到外壳。(这就是Perl代替不存在的SIGKILL发送的内容。

现在,我没有mimperf所以我使用了一个替代程序而不是mimperf(perl(,它收到了 Ctrl-Break 信号以及 shell。因此,如果mimperf没有退出,也许是因为它没有响应 Ctrl-Break?


如果你想避开外壳,你需要自己做输出重定向。为此,我推荐IPC::Run。它也处理超时。

use IPC::Run qw( run );
run [ "mimperf", "-C", $db ],
">", "results/mimperf/mimperf.log",
timeout(10);

最新更新