我尝试过使用无限循环的简单程序,我使用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
// 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);
}
}
// 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
...
...
..
答案 0 :(得分: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 {
...
exec
与system
类似,但它不是在新进程中启动命令,而是用运行命令的进程替换现有进程,保留进程ID。因此,在调用exec
之后,子perl进程将消失,$pid
将引用运行命令./loop.bin
的进程。现在您可以发信号$pid
,它将被发送到所需的过程。