php <defunct>,通过swoole观察僵尸进程和孤儿进程出现和消亡

声明:维基百科上没有僵死进程的词条,这里认为僵死进程同僵尸进程,即ZOMBIE。

一、定义

什么是僵尸进程

维基百科的定义:在类UNIX系统中,僵尸进程是指完成执行(通过exit系统调用,或运行时发生致命错误或收到终止信号所致)但在操作系统的进程表中仍然有一个表项(进程控制块PCB),处于”终止状态”的进程。

这个定义很准确,但并不好理解,通俗的说法是一个进程fork了一个子进程,子进程先于父进程退出,但父进程没有调用wait(通过wait系统调用读取退出进程的退出态,退出进程的在进程表中的表项就被删除),导致这个进程已经退出但是仍在进程表中占有一个位置,这种进程称为僵尸进程。

什么是孤儿进程

孤儿进程:一个进程fork了一个子进程, 父进程先于子进程退出,运行中的子进程称为孤儿进程。

孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。

下面,让我们来看2个示例:

二、僵尸进程示例

0、通过swoole在一个进程中创建子进程,让子进程先于父进程退出。

echo 'ppid = ' . getmypid(), PHP_EOL;

$process = new swoole_process(function (swoole_process $worker) {

echo 'pid = ' . getmypid(), PHP_EOL;

sleep(10);

echo 'child process exit', PHP_EOL;

}, false);

$process->start();

sleep(1000);

echo 'parent process exit', PHP_EOL;

1、以上代码保存文件zombie.php, 执行

[root@salmonl process]# php zombie.php

ppid = 4899

pid = 4900

child process exit

2、另开一个窗口查看进程

# 子进程退出前

$ ps aux | grep -v 'grep' | grep 'zombie'

root 4899 0.3 0.6 321644 24612 pts/0 S+ 16:07 0:00 php zombie.php

root 4900 0.0 0.2 321644 8956 pts/0 S+ 16:07 0:00 php zombie.php

# 子进程退出后

$ ps aux | grep -v 'grep' | grep 'zombie'

root 4899 0.0 0.6 321644 24612 pts/0 S+ 16:07 0:00 php zombie.php

# 查看僵尸进程(状态为Z, 或者COMMAND中出现defunct)

$ ps aux | grep -v 'grep' | grep 'defunct'

root 4900 0.0 0.0 0 0 pts/0 Z+ 16:07 0:00

3、kill僵尸进程无效

$ kill 4900

$ ps aux | grep -v 'grep' | grep 'defunct'

root 4900 0.0 0.0 0 0 pts/0 Z+ 16:07 0:00

4、kill父进程,僵尸进程就会消亡

$ kill 4899

$ ps aux | grep -v 'grep' | grep 'defunct'

三、孤儿进程示例

0、通过swoole在一个进程中创建子进程,让父进程先于子进程退出。

echo 'ppid = ' . getmypid(), PHP_EOL;

$process = new swoole_process(function (swoole_process $worker) {

echo 'pid = ' . getmypid(), PHP_EOL;

sleep(1000);

echo 'child process exit', PHP_EOL;

}, false);

$process->start();

sleep(10);

echo 'parent process exit', PHP_EOL;

1、以上代码保存文件orphan.php, 执行

$ php orphan.php

ppid = 5041

pid = 5042

parent process exit

2、另开一个窗口查看进程

# 父进程退出之前,进程状态

$ ps aux | grep -v 'grep' | grep 'orphan'

root 5041 0.5 0.6 321644 24612 pts/0 S+ 16:22 0:00 php orphan.php

root 5042 0.0 0.2 321644 8956 pts/0 S+ 16:22 0:00 php orphan.php

# 父进程退出之后进程状态(子进程的ppid变为1)

$ ps -ef | grep -v 'grep' | grep orphan

root 5042 1 0 16:22 pts/0 00:00:00 php orphan.php

四、总结

0、swoole中避免出现僵尸进程,在父进程中调用wait即可

while ($res = swoole_process::wait()) {

echo PHP_EOL, 'worker process exit pid: ' . $res['pid'] . PHP_EOL;

}

1、僵尸进程占用进程ID,多了之后,影响进程调度。

2、清除僵尸进程可通过清除父进程,或者等待很长时间后被内核清除。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值