僵尸进程

当子进程运行结束,父进程仍然继续运行,但父进程没有对子进程进行回收,释放子进程占用的资源,此时子进程就成为了一个僵尸进程。

在Unix进程管理中,如果新开的子进程运行结束,父进程将会收到一个SIGCHLD信号,子进程暂时成为僵尸进程,等待父进程进行处理。如果父进程一直不处理,该进程将会一直存在,占用系统进程表项,永久成为僵尸进程。如果僵尸进程过多,导致系统没有可用的进程表项,将无法运行其他的应用程序。

<?php
$str = "hello world!" . PHP_EOL;
$pid = pcntl_fork();
if ($pid > 0) {
echo "我是主进程,id是" . getmypid() . ",子进程的pid是{$pid}" . PHP_EOL;
pcntl_async_signals(true);
pcntl_signal(SIGCHLD, function () {
echo '子进程退出了,请及时处理' . PHP_EOL;
});
while (1) { //模拟主进程一直运行
sleep(1);
}
} elseif($pid==0) {
echo "我是子进程,我的pid是". getmypid() ."\n";
}else{
echo "我是主进程,开启子进程失败\n";
}

使用ps查看僵尸进程:

ps -A -ostat,ppid,pid,cmd | grep -e '^[Zz]'

终端会输出:

Z+     7136   7137 [php] <defunct>

当主进程退出之后,子进程将会被init接管并处理

使用 pcntl_wait 回收僵尸进程:

<?php
echo time() . PHP_EOL;
$pid = pcntl_fork();
if ($pid > 0) { //主进程代码
pcntl_wait($status); //父进程阻塞方式等待子进程的退出
echo time() . PHP_EOL;
} elseif($pid==0) {
sleep(3);
echo "我是子进程,我的pid是". getmypid() ."\n";
exit();
}else{
die("我是主进程,开启子进程失败\n");
}
1589874657
我是子进程,我的pid是16140
1589874660

pcntl_wait($status); 默认为阻塞方式回收子进程,可以设置第二个参数为 WNOHANG 即为非阻塞方式回收子进程,代码会继续往下执行,子进程退出后会自动回收。

多个子进程只需要一个pcntl_wait即可回收完成。

在父进程中,为SIGCHLD配置handler来回收:

<?php
pcntl_async_signals(true); pcntl_signal(SIGCHLD, function () {
echo "SIGCHLD" . PHP_EOL;
pcntl_wait($status); //父进程阻塞方式等待子进程的退出
}); echo time() . PHP_EOL;
$pid = pcntl_fork();
if ($pid > 0) { //主进程代码
sleep(10);
echo time() . PHP_EOL;
} elseif($pid==0) {
sleep(3);
echo "我是子进程,我的pid是". getmypid() ."\n";
exit;
}else{
die("我是主进程,开启子进程失败\n");
}
1589874039
我是子进程,我的pid是12875
SIGCHLD
1589874040

忽略子进程结束信号,由init回收:

<?php
pcntl_async_signals(true);
pcntl_signal(SIGCHLD, SIG_IGN); echo time() . PHP_EOL;
$pid = pcntl_fork();
if ($pid > 0) { //主进程代码
sleep(10);
echo time() . PHP_EOL;
} elseif($pid==0) {
sleep(3);
echo "我是子进程,我的pid是". getmypid() ."\n";
exit;
} else {
die("我是主进程,开启子进程失败\n");
}
1589874331
1589874331
我是子进程,我的pid是14493

孤儿进程

孤儿进程是指在其父进程执行完成或被终止后仍继续运行的一类进程。这些孤儿进程将被init进程收养,并由init进程对它们完成回收工作。

孤儿进程没有任何危害,只需要注意自己的代码逻辑即可。

<?php
$pid = pcntl_fork();
if ($pid == -1) {
die('fork error');
} elseif ($pid > 0) {
echo "爸爸先走了,儿子你好好干活" . PHP_EOL;
exit(); // 主进程在很短的时间内已经退出
} else {
// 子进程继续运行
$i = 10;
while($i) {
echo $i;
$i--;
sleep(1);
}
}
爸爸先走了,儿子你好好干活
1111111111...

孤儿进程与僵尸进程的区别

僵尸进程:一个子进程在其父进程还没有调用wait()或waitpid()的情况下退出,这个子进程就是僵尸进程。任何一个子进程在退出之后,并非马上就消失掉,而是留下一个称为僵尸进程的数据结构,等待父进程处理。这是每个子进程在结束时都要经过的阶段。如果子进程在退出之后,父进程没有来得及处理,那么子进程就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程。此为僵尸进程的危害,应当避免。

孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程收养,并由init进程对它们完成回收工作。每当一个孤儿进程出现,内核就把孤 儿进程的父进程设置为init,而init进程会循环地wait()已经退出的子进程。这样,当一个孤儿进程结束其生命周期的时候,init进程就会进行回收工作。因此孤儿进程并不会有什么危害 。

PHP 中的僵尸进程、孤儿进程详解的更多相关文章

  1. 进程,多进程,进程与程序的区别,程序运行的三种状态,multiprocessing模块中的Process功能,和join函数,和其他属性,僵尸与孤儿进程

    1.进程 什么是进程: 一个正在被运行的程序就称之为进程,是程序具体执行的过程,是一种抽象概念,进程来自操作系统 2.多进程  多个正在运行的程序 在python中实现多线程的方法 from mult ...

  2. day34 并行并发、进程开启、僵尸及孤儿进程

    day34 并行并发.进程开启.僵尸及孤儿进程 1.并行与并发 什么是并行? 并行指的是多个进程同时被执行,是真正意义上的同时 什么是并发? 并发指的是多个程序看上去被同时执行,这是因为cpu在多个程 ...

  3. 僵尸进程 & 孤儿进程

    参考博文 基本概念 僵尸进程:是所有进程都会进入的一种进程状态,子进程退出,而父进程并没有调用 wait() 或 waitpid() 获取子进程的状态信息,那么子进程的 PID 和 进程描述符 等资源 ...

  4. Go Exec 僵尸与孤儿进程

    原文地址:Go Exec 僵尸与孤儿进程 最近,使用 golang 去管理本地应用的生命周期,期间有几个有趣的点,今天就一起看下. 场景一 我们来看看下面两个脚本会产生什么问题: 创建两个 shell ...

  5. Python并发编程03 /僵孤进程,孤儿进程、进程互斥锁,进程队列、进程之间的通信

    Python并发编程03 /僵孤进程,孤儿进程.进程互斥锁,进程队列.进程之间的通信 目录 Python并发编程03 /僵孤进程,孤儿进程.进程互斥锁,进程队列.进程之间的通信 1. 僵尸进程/孤儿进 ...

  6. 「微信小程序」PHP异步进程async-helper实例详解

    PHP异步进程async-helper实例详解 PHP 的异步进程助手,借助于 AMQP 实现异步执行 PHP 的方法,将一些很耗时.追求高可用.需要重试机制的操作放到异步进程中去执行,将你的 HTT ...

  7. Java中堆内存和栈内存详解2

    Java中堆内存和栈内存详解   Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,ja ...

  8. 教程-Delphi中Spcomm使用属性及用法详解

    Delphi中Spcomm使用属性及用法详解 Delphi是一种具有 功能强大.简便易用和代码执行速度快等优点的可视化快速应用开发工具,它在构架企业信息系统方面发挥着越来越重要的作用,许多程序员愿意选 ...

  9. Linux中redis安装配置及使用详解

    Linux中redis安装配置及使用详解 一. Redis基本知识 1.Redis 的数据类型 字符串 , 列表 (lists) , 集合 (sets) , 有序集合 (sorts sets) , 哈 ...

  10. Android 中各种权限深入体验及详解

    Android 中各种权限深入体验及详解 分类: Android2012-07-15 19:27 2822人阅读 评论(0) 收藏 举报 androidpermissionsinstallersyst ...

随机推荐

  1. java Map集合类

    ---恢复内容开始--- Map提供了一个更通用的元素存储方法,Map集合类用于存储元素对(称作"键"和"值"),其中每个键映射到一个值. 了解Map接口和方法 ...

  2. 关于form表单提交ajaxForm和ajaxSubmit的用法与区别

    前几天在学习form表单提交时看到这两种方法,这两种方法都是实现form的ajax提交的方法,看了很多资料还是不太明白其用法和区别,最后直接自己写demo,很快就理解,所以说实操是学习的最快捷直接的途 ...

  3. go goroutines 使用小结

    go +方法 就实现了一个并发,但由于环境不同,需要对并发的个数进行限制,限制同一时刻并发的个数,后面称此为"并发限流". 为什么要并发限流? 虽然GO M+P+G的方式号称可以轻 ...

  4. java-阿里邮件推送服务开发 -- 发送邮箱验证码

    参考文档: 如何在 DNS 服务器上配置域名:https://help.aliyun.com/knowledge_detail/39397.html?spm=5176.2020520150.102.d ...

  5. Oracle 用户自定义数据类型

    用户自定义数据类型(User-defined Data Type)oracle支持对象类型(Object Type).嵌套类型(Nested Table Type)和可变数组类型(Varray Dat ...

  6. linux查询健康状态,如何直观的判断你的Linux系统是否健康

    一提到对于查看系统运行的健康状况,可能大多数朋友考虑到的就是查看进程或者打开任务管理器,但是对于应用在真实生产环境中服务器的linux系统来说,以上两种方式都不是***效的查看方式,那么今天就给大家推 ...

  7. 【Service】【Database】【MySQL】基础

    1. 概念 1.1. 作者:Unireg 1.2. MySQL AB --> MySQL Solaris:二进制版本: 1.3. 官方网站: MySQL: www.mysql.com Maria ...

  8. 数据挖掘实战 - 天池新人赛o2o优惠券使用预测

    数据挖掘实战 - o2o优惠券使用预测 一.前言 大家好,家人们.今天是2021/12/14号.上次更新是2021/08/29.上篇文章中说到要开两个专题,果不其然我鸽了,这一鸽就是三个多月.今天,我 ...

  9. 象群游牧算法-Matlab

    1. 适应度函数: function z=chaffer(x)%chaffer函数x=(0...0) f(x)=0 x[-10,10]%%没测 n=10; s1=0; for i=1:n s1=s1+ ...

  10. git 省略 commit message

    每次提交使用 git commit --allow-empty-message --no-edit 也可以设置命令别名 git config --global alias.nocommit " ...