杀死在infinte循环中通过system()函数运行的子进程在perl中不起作用

day*_*mer 3 perl

我尝试过无限循环的简单程序,我使用PERL脚本运行它并在10次睡眠后试图杀死它,但是我的程序没有杀死子进程并且在无限循环中运行.

// C代码:$ cat loop.c

#include <stdio.h>
int main(){

while(1){
 printf("Infinite loop\n");
        }

return 0;
}


$ gcc loop.c -o loop.bin
Run Code Online (Sandbox Code Playgroud)

// PERL CODE $ cat timeout.pl

#!/usr/bin/perl

use strict;
use warnings;
use POSIX ":sys_wait_h";
use Time::HiRes qw(sleep);

if(!defined( my $pid = fork())) {
die "Cannot fork a child: $!";
} elsif ($pid == 0) {
   print "Printed by child process\n";
   system("./loop.bin");
} else {
   print "Printed by parent process\n";
   sleep(10);
   my $ret = waitpid($pid, WNOHANG);

   if ($ret == 0){
     kill ('KILL',$pid);
         sleep(1);
         }
   }
Run Code Online (Sandbox Code Playgroud)

// OUTPUT:执行后,perl脚本不会终止子进程(./TC_1.bin)$ perl timeout.pl

Printed by child process
Infinite loop
Infinite loop
Infinite loop
Infinite loop
Infinite loop
Infinite loop
Infinite loop
Infinite loop
...
...
..
Run Code Online (Sandbox Code Playgroud)

mob*_*mob 5

$pid是由fork调用创建的子进程的进程ID .这是一个perl进程.当您调用system($command)时,会创建一个新进程,运行该命令$command,并且您不知道该命令的进程ID是什么.调用kill('KILL',$pid)向后台perl进程发送信号,但不一定发送给任何子进程,因此您无法确定该system呼叫是否也会收到该信号.

一种解决方案是使用exec而不是system.

...
} elsif ($pid == 0) {
   print "Printed by child process\n";
   exec("./loop.bin");
} else {
...
Run Code Online (Sandbox Code Playgroud)

exec就像system,但不是在新进程中启动命令,而是用运行命令的进程替换现有进程,保留进程ID.因此,在调用之后exec,子perl进程将消失,$pid并将引用运行该命令的进程./loop.bin.现在您可以发出信号$pid并将其发送到所需的过程.