PHP 中的僵尸进程、孤儿进程详解
僵尸进程
当子进程运行结束,父进程仍然继续运行,但父进程没有对子进程进行回收,释放子进程占用的资源,此时子进程就成为了一个僵尸进程。
在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 中的僵尸进程、孤儿进程详解的更多相关文章
- 进程,多进程,进程与程序的区别,程序运行的三种状态,multiprocessing模块中的Process功能,和join函数,和其他属性,僵尸与孤儿进程
1.进程 什么是进程: 一个正在被运行的程序就称之为进程,是程序具体执行的过程,是一种抽象概念,进程来自操作系统 2.多进程 多个正在运行的程序 在python中实现多线程的方法 from mult ...
- day34 并行并发、进程开启、僵尸及孤儿进程
day34 并行并发.进程开启.僵尸及孤儿进程 1.并行与并发 什么是并行? 并行指的是多个进程同时被执行,是真正意义上的同时 什么是并发? 并发指的是多个程序看上去被同时执行,这是因为cpu在多个程 ...
- 僵尸进程 & 孤儿进程
参考博文 基本概念 僵尸进程:是所有进程都会进入的一种进程状态,子进程退出,而父进程并没有调用 wait() 或 waitpid() 获取子进程的状态信息,那么子进程的 PID 和 进程描述符 等资源 ...
- Go Exec 僵尸与孤儿进程
原文地址:Go Exec 僵尸与孤儿进程 最近,使用 golang 去管理本地应用的生命周期,期间有几个有趣的点,今天就一起看下. 场景一 我们来看看下面两个脚本会产生什么问题: 创建两个 shell ...
- Python并发编程03 /僵孤进程,孤儿进程、进程互斥锁,进程队列、进程之间的通信
Python并发编程03 /僵孤进程,孤儿进程.进程互斥锁,进程队列.进程之间的通信 目录 Python并发编程03 /僵孤进程,孤儿进程.进程互斥锁,进程队列.进程之间的通信 1. 僵尸进程/孤儿进 ...
- 「微信小程序」PHP异步进程async-helper实例详解
PHP异步进程async-helper实例详解 PHP 的异步进程助手,借助于 AMQP 实现异步执行 PHP 的方法,将一些很耗时.追求高可用.需要重试机制的操作放到异步进程中去执行,将你的 HTT ...
- Java中堆内存和栈内存详解2
Java中堆内存和栈内存详解 Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,ja ...
- 教程-Delphi中Spcomm使用属性及用法详解
Delphi中Spcomm使用属性及用法详解 Delphi是一种具有 功能强大.简便易用和代码执行速度快等优点的可视化快速应用开发工具,它在构架企业信息系统方面发挥着越来越重要的作用,许多程序员愿意选 ...
- Linux中redis安装配置及使用详解
Linux中redis安装配置及使用详解 一. Redis基本知识 1.Redis 的数据类型 字符串 , 列表 (lists) , 集合 (sets) , 有序集合 (sorts sets) , 哈 ...
- Android 中各种权限深入体验及详解
Android 中各种权限深入体验及详解 分类: Android2012-07-15 19:27 2822人阅读 评论(0) 收藏 举报 androidpermissionsinstallersyst ...
随机推荐
- @Deprecated注解功能
@Deprecated注解功能 标记不建议使用的方法,但是仍然可以用 当方法有更好的方法替换时,但是此方法还有使用时可以使用该注解
- 【VSCode】检测到 #include 错误。请更新 includePath。已为此翻译单元(C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\i686-
win+r 运行cmd 输入"gcc -v -E -x c -"获取mingw路径: 我的: #include "..." search starts here ...
- 【HarmonyOS】【xml】使用xml绘制视频播放控制栏
本文记录HarmonyOS使用xml绘制视频播放控制栏 效果图如下 代码如下 点击查看代码 <?xml version="1.0" encoding="utf-8& ...
- Linux目录终章,单用户模式修改密码、环境变量、第三方软件安装
目录 今日内容概要 内容详细 解析映射文件 磁盘挂载文件 开机加载脚本 系统启动级别 使用单用户模式修改密码 变量加载文件 登录提示信息 第三方软件安装目录(编译安装目录) 系统日志目录 保存系统运行 ...
- Mysql资料 查询SQL执行顺序
目录 一.Mysql数据库查询Sql的执行顺序是什么? 二.具体顺序 一.Mysql数据库查询Sql的执行顺序是什么? (9)SELECT (10) DISTINCT column, (6)AGG_F ...
- 什么是git?
目录 一.简介 Git与SVN 区别 一.简介 Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目. Git 是 Linus Torvalds 为了帮助管理 Linux 内核 ...
- EmmyLua 注解功能
前言 网上配置 EmmyLua 的方法很多,此处就不做赘述(因此前提是你已经安装配置完EmmyLua) 本文仅是对 EmmyLua插件 内 注解功能 用法的代码演示.因为网上大部分EmmyLua配置教 ...
- 通过Docker部署Java项目的日志输出到宿主机指定目录
之前写过2篇关于Docker部署的文章: 1.超!超!超简单,Linux安装Docker 2.Docker通过阿里云镜像仓库使用Gitlab_CI部署SpringBoot项目 用上篇博客部署Java程 ...
- 2020信息安全铁人三项 pwn复盘
第一赛区 hacknote 程序存在格式化字符串漏洞和uaf,不多说了,很简单. 1 from pwn import * 2 3 p = process('./hacknote') 4 elf = E ...
- CF1064A Make a triangle! 题解
Content 有三条长度分别为 \(a,b,c\) 的线段.你可以在一个单位时间内将一条线段的长度增加 \(1\),试求出能使这三条线段组成一个三角形的最短时间. 数据范围:\(1\leqslant ...