僵尸进程

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

在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. OpenStack之四: keystone验证服务(端口5000)

    #官网地址:https://docs.openstack.org/keystone/stein/install/keystone-install-rdo.html #:创建库,并授权 MariaDB ...

  2. 手写Mybatis和Spring整合简单版示例窥探Spring的强大扩展能力

    Spring 扩展点 **本人博客网站 **IT小神 www.itxiaoshen.com 官网地址****:https://spring.io/projects/spring-framework T ...

  3. Unity实现“笼中窥梦”的渲染效果

    效果 思路 5个面用5个RenderTexture来接受5个摄像机分别获取的小场景图像: RenderTexture就当成屏幕来理解,MainCamera是把画面显示在屏幕上,屏幕就是最大的Rende ...

  4. 基于Github Actions + Docker + Git 的devops方案实践教程

    目录 为什么需要Devops 如何实践Devops 版本控制工具(Git) 学习使用 配置环境 源代码仓库 一台配置好环境的云服务器 SSH远程登录 在服务器上安装docker docker技术准备工 ...

  5. IDE常用插件

    IDE 常用插件集合 :

  6. 多个工作簿拆分(Excel代码集团)

    一个文件夹里有N个工作簿,每个工作簿中包括N个工作表,将各个工作表拆分成工作簿,命名为每个工作簿里第一个工作表的A列和B列. 工作簿.工作表数量不定,表内内容不限,拆分后保存于当前文件夹下的" ...

  7. 『学了就忘』Linux系统管理 — 86、查看系统资源相关命令

    目录 1.vmstat命令 2.dmesg命令 3.free命令 4.查看CPU信息 5.查看本机登陆用户信息 (1)w命令 (2)who命令 6.uptime命令 7.查看系统与内核相关信息 1.v ...

  8. CF205A Little Elephant and Rozdil 题解

    Content 有一头小象住在 \(\texttt{Rozdil}\) 小镇里,它想去其他的小镇旅行. 这个国家一共有 \(n\) 个小镇,第 \(i\) 个小镇距离 \(\texttt{Rozdil ...

  9. LuoguP7911 [CSP-J 2021] 网络连接 题解

    Content 题目过于难解释,请前往题面查看.以下直接给出本题做法. Solution 入门组 T3 在我印象中向来都不是很容易能做出来的题目,但是今年这个 T3 不得不说还是挺好做的. 我们先不妨 ...

  10. LuoguP5006 [yLOI2018] 大美江湖 题解

    Content 题意实在是太过复杂了,因此请回到题面查看. Data Range 本部分和 Solution 部分变量的含义同题面. \(1\leqslant n,m\leqslant 100,0\l ...