PHP多进程(二)

news2024/11/24 17:43:51

上篇文章我们说到父进程应该回收子进程结束之后产生的数据,这样才会不浪费系统资源。

一个程序启动之后,变成了一个进程,进程在以下情况会退出
1)运行到最后一行语句
2) 运行时遇到return 时
3) 运行时遇到exit()函数的时候
4) 程序异常的时候
5) 进程接收到中断信号

这篇我们认识一个新的函数

pcntl_wait 进程的退出

PHP: pcntl_wait - Manual

pcntl_wait — 等待或返回 fork 的子进程状态

wait函数挂起当前进程的执行直到一个子进程退出或接收到一个信号要求中断当前进程或调用一个信号处理函数如果一个子进程在调用此函数时已经退出( 俗称僵尸进程 ),此函数立刻返回。子进程使用的所有系统资源将被释放。

意思就是说pcntl_wait默认是阻塞状态等待子进程结束,如果子进程没有通过wait回收的话就会变成一个僵尸进程占用资源

僵尸进程

演示僵尸进程前,先来能识别什么是僵尸进程

# linux命令行

ps -aux  


# 筛选php的进程

ps -aux | grep php  



# 进程状态  对应下图红线处

D 不可中断 Uninterruptible(usually IO)

R 运行状态,正在运行

S 处于休眠状态,是可被系统唤醒

T 停止状态

Z 僵尸进程

W 进入内存交换(从内核2.6开始无效)

X 死掉的进程

演示僵尸进程:

$pid = pcntl_fork(); // 开启子进程

if ($pid == 0){
    // 子进程运行结束 并没有被父进程回收的进程 就是僵尸进程
    echo "我是子进程,我的标识是:".posix_getpid().",好了我的任务结束了,拜拜"."\n";
}else{
    echo "我是父进程,我的标识是:".posix_getpid()."\n";
    // 父进程有任务还在运行的时候子进程已经结束了 这个时候子进程的垃圾并未被回收 还在占用这系统资源
    while (1){
        ;
    }
}

# 三种查看方式

pstree -ap | grep php


ps -ef | grep php


ps -aux | grep php

 

# /proc文件系统提供有关系统中进程的信息

ls /proc/

# 查看进程资源

ls /proc/{pid} 

 当我ctrl+c终止掉这个程序的时候,僵尸进程也就不存在了

 让我们来使用pcntl_wait()回收

$pid = pcntl_fork(); // 开启子进程

if ($pid == 0){
    echo "我是子进程,我的标识是:".posix_getpid().",(我接到了爸爸的电话,让我回家去),好,出发"."\n";
    echo "我距离我爸是15步"."\n";
    // 子进程运行任务
    $i = 0;
    while ($i<=14){
        echo "爸爸,我正在回家去,我走了".($i+1).'步'."\n";
        $i++;
        sleep(2);
    }

}else{
    echo "我是父进程,我的标识是:".posix_getpid().',过年了,我打电话让我儿子回家了'."\n";

    $exitPid = pcntl_wait($status);   // 阻塞状态就是一直等待子进程并回收
    echo "我儿子回来了,我的儿子是:".$exitPid."\n";
}

当儿子回家的时候我们通过另外一个连接查看儿子回家的状态

 我们这次子进程不用sleep()函数再看一下效果

$pid = pcntl_fork(); // 开启子进程

if ($pid == 0){
    echo "我是子进程,我的标识是:".posix_getpid().",(我接到了爸爸的电话,让我回家去),好,出发"."\n";
    // 子进程运行任务
    while (1){
        ;
    }

}else{
    echo "我是父进程,我的标识是:".posix_getpid().',过年了,我打电话让我儿子回家了'."\n";

    $exitPid = pcntl_wait($status);   // 阻塞状态就是一直等待子进程并回收
    echo "我儿子回来了,我的儿子是:".$exitPid."\n";
}

我们再来看一下pcntl_wait()参数

pcntl_wait() 将会存储状态信息到 status 参数上,这个通过 status 参数返回的状态信息可以用以下函数 pcntl_wifexited(), pcntl_wifstopped(), pcntl_wifsignaled(), pcntl_wexitstatus(), pcntl_wtermsig() 以及 pcntl_wstopsig() 获取其具体的值。

pcntl_wait() 返回退出的子进程进程号,发生错误时返回 -1,如果提供了 WNOHANG 作为 option(wait3可用的系统)并且没有可用子进程时返回 0。

根据官网的例子说明,接下来我们分别测试:

$pid = pcntl_fork(); // 开启子进程

if ($pid == 0){
    echo "子进程标识是:".posix_getpid()."\n";


    // while (1){
    //     ;
    // }

}else{

    echo "父进程标识是:".posix_getpid()."\n";

    // 不阻塞状态 $exitPid 是返回 0  阻塞状态会等待子进程回收并返回子进程pid
    // 参数二就是不阻塞状态
    $exitPid = pcntl_wait($status,WNOHANG);   // 非阻塞
    // $exitPid = pcntl_wait($status);                // 阻塞

    // $exitPid 有三种状态 成功回收子进程 > 0  失败就是 -1  没有可用子进程返回 0
    // 我们这样就可以增加判断
    if ($exitPid == 0){

        echo "没有可回收进程"."\r\n";

    }elseif($exitPid > 0){

        // 回收子进程成功
        echo "回收子进程成功"."\n";

    }
}

进程退出以及退出状态演示:

// 北风之神yyds
// 1) return exit 函数 正常终止退出
// 2) 中断信号 异常终止退出
// 进程不管是何种方式退出,都会有一部分数据驻留在内存中,比如说终止状态,所以父进程必须使用pcntl_wait函数来回收终止进程所占用的系统资源
// 僵尸进程:就是子进程已经退出,但父进程还没有回收[pcntl_wait] Z
$pid = pcntl_fork(); // 开启子进程

if ($pid == 0){
    echo "子进程标识是:".posix_getpid()."\n";
    // die(5);
    // exit(7);
    // return 1;
    while (1){
        ;
    }

}else{

    echo "父进程标识是:".posix_getpid()."\n";

    // 不阻塞状态 $exitPid 是返回 0  阻塞状态会等待子进程回收并返回子进程pid
    // 参数二就是不阻塞状态
    // $exitPid = pcntl_wait($status,WNOHANG);   // 非阻塞
    $exitPid = pcntl_wait($status);                // 阻塞

    // $exitPid 有三种状态 成功回收子进程 > 0  失败就是 -1  没有可用子进程返回 0
    // 我们这样就可以增加判断
    if ($exitPid == 0){

        echo "没有可回收进程"."\r\n";

    }elseif($exitPid > 0){

        // 回收子进程成功了
        echo "回收子进程成功"."\n";

        // 接下来我们来判断退出状态

        if (pcntl_wifexited($status)){

            // pcntl_wifexited 检查子进程状态代码是否代表正常退出。正常退出时返回 true ,其他情况返回 false。
            // pcntl_wexitstatus  返回一个中断的子进程的返回代码
            echo "子进程是正常退出!"."代码是".pcntl_wexitstatus($status)."\n";

        }elseif (pcntl_wifstopped($status)){

            // 这个不知道怎么演示出来 *****  我测试 SIGSTOP SIGTSTP 这两个让进程停止的方法 不会进入到这里

            // pcntl_wifstopped  检查子进程当前是否已经停止 进程当前是停止的返回 true ,其他情况返回 false 。
            // pcntl_wstopsig 返回导致子进程停止的信号 返回信号编号。
            echo "子进程停止退出!停止信号是:".pcntl_wstopsig($status)."\n";

        }elseif (pcntl_wifsignaled($status)){

            // pcntl_wifsignaled 检查子进程状态码是否代表由于某个信号而中断 子进程是由于某个未捕获的信号退出的返回 true ,其他情况返回 false 。
            // pcntl_wtermsig  返回导致子进程中断的信号  返回整型的信号编号。
            echo "子进程非正常退出!中断信号是:".pcntl_wtermsig($status)."\n";

        }
    }
}

暂时不知道怎么测试出进程停止退出的状态

我测试信号 SIGSTOP SIGTSTP 这两个让进程停止的方法,也不行

所以跳过........

 关于信号

# 查看所有信号

kill -l

可以参考别的大佬的文章

Linux 信号的详细介绍和举例说明_易点点心动的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/158040.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Dash搭建可视化网站】项目13:销售数据可视化大屏制作步骤详解

销售数据可视化大屏制作步骤详解1 项目效果图2 项目架构3 文件介绍和功能完善3.1 assets文件夹介绍3.2 app.py和index.py文件完善3.3 header.py文件完善3.4 api.py文件和api.ipynb文件完善3.4.1 需求数据获取3.4.2 header.py文件中数据变更3.5 middle.py文件完善3.5.1 中间第一…

24.数组名字取地址变成数组指针,数组名和指针变量的区别

数组名字取地址变成数组指针 1.一维数组名字取地址&#xff0c;变成一维数组指针&#xff0c;加1跳一个一维数组。 int a[10]; a1 跳一个整型元素&#xff0c;是a[1]的地址 a和a1相差一个元素&#xff0c;4个字节 &a 就变成了一个一位数组指针&#xff0c;是int(*p)[10]…

结构体重点知识大盘点

0、结构体基础知识 1、结构体是一些值的集合&#xff0c;这些值被称为成员&#xff0c;它们的类型是可以不同的。&#xff08;与数组相似&#xff0c;但数组元素的类型都是相同的&#xff09;。用来描述由基本数据类型组成的复杂类型。 2、结构体也有全局的和局部的。 3、st…

Hello World with VS 17.4.4 DOT NET MAUI Note

Hello World with VS 17.4.4 DOT NET MAUI Note kagula2023-1-12 Prologue If you touched XAML, well here is a concise guide for you running the first MAUI project. Content System Requirement 【1】Microsoft Windows [Version 10.0.19044.2486] Chinese Language …

Ubuntu Centos Linux End Kernel panic-not syncing:Attempted to kill init!

原问题&#xff1a; 当前系统为 Ubuntu 解决问题步骤&#xff1a; 1、重启电脑&#xff0c;在进入选择版本时&#xff0c;选择 系统高级选项&#xff0c; 我选的是【Ubuntu高级选项】 2、进入一个又很多系统版本的界面&#xff0c;每个版本有三个选项&#xff1a;常规启动版…

如何在 ASP.NET Core 2.X 项目中通过EF Core使用MySQL数据库

目录 一、安装MySql.Data.EntityFrameworkCore 二、创建EF Core上下文类以及相关数据模型类 三、配置连接字符串 四、在Starup.cs中注册数据库服务&#xff08;配置Context类的依赖注入&#xff09; 五、通过数据迁移命令生成数据库 目前EF Core已经支持了MySQL数据库了。…

从零开始带你实现一套自己的CI/CD(四)Jenkins Pipeline流水线

目录一、简介二、Groovy2.1 HelloWorld2.2 Pipeline script from SCM三、Jenkinsfile3.1 拉取代码3.2 代码质量检测3.3 构建代码3.4 制作镜像并发布镜像仓库3.5 部署到目标服务器3.6 完整的Jenkinsfile3.7 参数配置3.8 通过参数构建四、添加邮件通知4.1 配置Jenkins邮件配置4.2…

开源飞控初探(一):无人机的历史

这章先纠正大疆带给无人机外行小白的认知。定义无人机无人机的正式英文名字是Unmanned Aerial Vehicle&#xff0c;缩写为UAV。有人无人的区分&#xff0c;是看飞机能否一直需要人为操控。最简单的场景是&#xff0c;当飞机飞出视线之外时&#xff0c;人已经很难实时根据环境来…

微服务自动化管理【docker compose】

1.什么是docker-compose Docker-Compose项目是Docker官方的开源项目&#xff0c;负责实现对Docker容器集群的快速编排 通过编写docker-compose文件可对多个服务同时进行启动/停止/更新(可定义依赖&#xff0c;按顺序启动服务) docker-compose将所管理的容器分为3层结构&#…

Yii2下PHP远程调试PHP5.6/7.2与Xdebug2.5/2.7/3.0 在PHPSTORM下的差异化表现

学习起因&#xff1a;新人学YII2不知道远程调试(远程调试和控制台调试是两件事&#xff0c;同一个原理) 因为yii2框架&#xff0c;设计复杂度非常高&#xff0c;加上php代码的弱类型语言结构&#xff0c;在代码非常复杂的情况下&#xff0c;不采用调试的方式来看源码调用栈&am…

MPLS 虚拟专线 实验

目录 1.拓扑图 2.实验思路 3.主要配置 4.测试 5.实验总结 1.拓扑图 2.实验思路 IGP路由 MPLS Domain 配置MPLS VPN PE之间的MP-BGP邻居关系 CE端与PE端的路由交换 双向重发布&#xff0c;实现路由共享 3.主要配置 R6&#xff1a; *公网环境&#xff1a; [r6]ospf 1 r…

记录robosense RS-LIDAR-16使用过程2

一、安装并使用可视化工具RSView&#xff0c;官网提供了不同版本的安装包&#xff0c;根据个人环境下载解压。本人ubuntu18系统&#xff0c;修改权限&#xff1a;chmod ax run_rsview.sh;然后运行&#xff1a;./run_rsview.sh。该软件每次启动时都要运行./run_rsviewer.sh该软件…

Acwing 1214. 波动数列

题目链接&#xff1a;1214. 波动数列 - AcWing题库 标签&#xff1a;动态规划 &#xff08;字好丑...&#xff09; AC代码&#xff1a; #include<iostream> using namespace std;int f[1005][1005];const int MOD 100000007;//返回正余数 int get_mod(int a,int b) {…

不重复的随机数问题

前言 对于随机数的运用&#xff0c;在开发中经常会用到。有时需要生成不重复的定范围定总量的随机数&#xff0c;比如1~20&#xff0c;需要打乱的1~20中的10个数&#xff0c;那到底怎么做呢? 一、不重复的随机数 我们知道&#xff0c;直接用random会有重复的数字&#xff0…

电商物流云仓的原理是什么?

以云的速度和范围获得胜利  这是一个快速转型时期&#xff0c;封锁、就地避难订单和游览限制扰乱了美国经济的各个范畴&#xff0c;对供给链运营产生了严重影响。在如此动乱的时期&#xff0c;企业正越来越多地转向云优先战略&#xff0c;以使其供给链愈加矫捷和灵敏。  战…

【NI Multisim 14.0原理图文件管理——保存/备份文件及新建电路图页文件】

目录 序言 ⛄1.保存文件 ⛄2.备份文件 ⛄3.新建电路图页文件 序言 NI Multisim最突出的特点之一就是用户界面友好。它可以使电路设计者方便、快捷地使用虚拟元器件和仪器、仪表进行电路设计和仿真。 首先启动NI Multisim 14.0&#xff0c;打开如图所示的启动界面&#xff…

CTK Plugin Framework插件框架学习--事件监听

文章目录一、前言二、框架事件三、插件事件四、服务事件五、添加事件监听一、前言 CTK一共有三种事件可以监听&#xff1a; 框架事件插件事件服务事件 但是这些事件只有在变化时才能监听到&#xff0c;如果已经变化过后&#xff0c;进入一个稳定的状态&#xff0c;这时才去监…

归并排序详细说明及实现-python

算法思想&#xff1a; 设初始序列含有n个记录&#xff0c;则可看成n个有序的子序列&#xff0c;每个子序列长度为1 两两合并&#xff0c;得到&#xff08;n//2) 个长度为2&#xff08;n为奇数时&#xff0c;最后一个序列的长度为1&#xff09;的有序子序列 再两两合并&#xff…

【Flink系列】开发篇:1. Flink维表关联方案

数据流往往需要访问外部的数据源来丰富自己的信息&#xff0c;比如通过record中的ip地址查询ip数据库maxmind的GeoIP2 Databases得到ip对应的城市名称&#xff0c;城市经纬度&#xff0c;将这些作为新的字段添加到原来的record中。这就涉及到本篇的主题&#xff1a;维表关联。 …

分布式锁方案分析:看图说话(图+文)

1 缘起 曾经在看分布式锁的时候&#xff0c;还是处于了解阶段&#xff0c; 回头总结时&#xff0c;发现有很多细节没有探究到&#xff0c; 本文以-看图说话的方式分析不同的分布式锁方案&#xff0c; 分布式锁需要保证&#xff1a; &#xff08;1&#xff09;互斥性&#xff1…