我正在尝试使用fork,exec在perl中启动android模拟器。之后我也需要杀掉它,但是杀死它会导致模拟器在后台运行的僵尸进程。
我尝试使用kill -1
以及kill -9
和killall -v emulator
进行查杀。我也尝试通过附加显式exec(“exec命令...”)来执行exec'ing,但无论哪种方式,我都会得到一个僵尸进程,直到perl脚本运行。
这是我的代码:
my $CMD;
my $PID;
sub waitkey()
{
local( $| ) = ( 1 );
print "Press <Enter> or <Return> to continue: ";
my $resp = <STDIN>;
}
$|++;
$CMD = "emulator -avd audit -no-snapshot-save";
# $CMD = "exec emulator -avd audit -no-snapshot-save";
$PID = fork();
if ($PID==0)
{
print "forked!\n\n";
sleep(1);
exec("$CMD");
die "Unable to execute";
}
print "PID: $PID\n\n";
sleep(1);
print "------ Processes before killing -----\n";
print `ps aux | grep emulator`;
print "------ Press a key to kill -----\n\n"
&waitkey;
# `kill -1 $PID`;
`kill -9 $PID`;
print "------ Processes after killing -----\n";
sleep(1);
print `ps aux | grep emulator`;
print "----- waiting ... -----\n";
#-- do somehing here with assumption that emulator has been killed --
&waitkey;
在输出中我看到
------ Processes before killing -----
qureshi 10561 0.0 0.0 3556 980 pts/5 S+ 13:28 0:00 emulator -avd audit -no-snapshot-save
qureshi 10562 0.0 0.0 4396 616 pts/5 S+ 13:28 0:00 sh -c ps aux | grep emulator
qureshi 10564 0.0 0.0 13580 928 pts/5 S+ 13:28 0:00 grep emulator
并且在杀死进程后
------ Processes after killing -----
qureshi 10561 30.0 0.0 0 0 pts/5 R+ 13:28 0:01 [emulator64-arm]
qureshi 10619 0.0 0.0 4396 612 pts/5 S+ 13:28 0:00 sh -c ps aux | grep emulator
qureshi 10621 0.0 0.0 13580 932 pts/5 S+ 13:28 0:00 grep emulator
如何摆脱僵尸进程?
答案 0 :(得分:5)
僵尸只是一个进程表条目,它正在等待父进程来到并收集其退出状态。如perldoc fork中所述,
如果你在没有等待孩子的情况下分叉,你就会积累 僵尸。在某些系统上,您可以通过将$ SIG {CHLD}设置为来避免这种情况 “IGNORE”。
设置$SIG{CHLD}
适用于大多数unix类型的系统,包括Linux,因此这是安排孩子安息的最简单方法。
顺便说一句,使用&
前缀调用用户定义的函数是Perl 4-ism。在当前的Perl版本中,您应该只使用waitkey
或waitkey()
而不是&waitkey
。
答案 1 :(得分:4)
在杀死子进程后,您应该在父进程中使用waitpid
。这是因为您使用fork
来获取新进程,Perl不会像system
那样为您执行清理工作。
但是我推荐CPAN中的a better module做了整个凌乱的事情,我觉得非常方便。