【问题标题】:Perl fork(), exec() and then kill creating zombie processPerl fork(), exec() 然后杀死创建僵尸进程
【发布时间】:2013-03-19 08:32:52
【问题描述】:

我正在尝试使用 fork、exec 在 perl 中启动 android 模拟器。之后我也需要杀死它,但杀死它会导致僵尸进程在后台运行模拟器。

我尝试过使用kill -1 以及kill -9killall -v emulator 进行杀戮。我还尝试通过附加显式 exec("exec command ...") 来执行 exec,但无论哪种方式,我都会得到一个僵尸进程,直到 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

如何摆脱僵尸进程?

【问题讨论】:

    标签: perl fork


    【解决方案1】:

    僵尸只是一个进程表条目,它等待父进程过来并收集其退出状态。如perldoc fork 中所述,

    如果你不等孩子就分叉,你会积累 僵尸。在某些系统上,您可以通过将 $SIG{CHLD} 设置为 “忽略”。

    设置 $SIG{CHLD} 适用于大多数 unix 类型的系统,包括 Linux,因此这是让您的孩子安静休息的最简单方法。

    顺便说一句,使用 &amp; 前缀调用用户定义的函数是 Perl 4-ism。在当前的 Perl 版本中,您应该只使用 waitkeywaitkey() 而不是 &amp;waitkey

    【讨论】:

      【解决方案2】:

      你应该在杀死子进程后在父进程中使用waitpid。那是因为你使用fork 来获得一个新进程,Perl 不会像system 那样为你做清理工作。 但我推荐在 CPAN 中使用 a better module 来完成整个混乱的事情,我觉得它非常方便。

      【讨论】:

        猜你喜欢
        • 2013-06-01
        • 2011-09-14
        • 2014-06-19
        • 1970-01-01
        • 1970-01-01
        • 2015-04-12
        • 1970-01-01
        • 2015-02-06
        • 2014-09-30
        相关资源
        最近更新 更多