参考 基于PCNTL的PHP并发编程

PCNTL 是 PHP 中的一组进程控制函数,可以用来 fork(创建)进程,传输控制信号等。

在PHP中,进程控制支持默认关闭。编译时通过 --enable-pcntl 配置选项可以使 PHP的 CGI 或 CLI 版本打开进程控制支持(但是注意不要在 web 服务器中用 PCNTL,会导致不可预料的问题)。仅 Unix 类系统支持 PCNTL 模块。

PCNTL 原理

简单示例

<?php

//在当前进程当前位置产生分支(子进程)
$pid = pcntl_fork(); //父进程和子进程都会执行下面代码
if ($pid == -1) {
//错误处理:创建子进程失败时返回-1.
die('could not fork');
} else if ($pid) {
//父进程会得到子进程号,所以这里是父进程执行的逻辑
pcntl_wait($status); //等待子进程中断,防止子进程成为僵尸进程。
} else {
//子进程得到的$pid为0, 所以这里是子进程执行的逻辑。
}

原理

PCNTL 中的一系列函数,都对应操作系统中的函数,例如 pcntl_fork 就对应 Linux 系统中的 fork 函数。

每次在进程中调用 fork 函数时,操作系统会把进程完整的复制一份,作为这个进程的子进程。此时,两个进程的唯一区别就是 PID(进程ID)和 PPID(父进程ID)。根据 fork 返回值的不同可以判断当前是在父进程还是子进程中,从而可以有不同的处理逻辑。

为了保证系统资源利用率,必须防止出现僵尸进程(进程结束后未回收资源)或孤儿进程(父进程提前结束),可以通过 pcntl_wait 或 pcntl_waitpid 函数来监控子进程。

常用函数

pcntl_fork

在当前进程的当前位置产生分支(子进程),父进程和子进程都从fork的位置开始向下继续执行,不同的是父进程执行过程中,得到的fork返回值为子进程号,而子进程得到的是0。子进程仅PID(进程号) 和PPID(父进程号)与其父进程不同。

语法:

int pcntl_fork ( void )

返回值:

  • 成功时,产生进程分支:

    • 在父进程执行线程内返回产生的子进程的PID
    • 在子进程执行线程内返回0
  • 失败时,在 父进程上下文返回-1,不会创建子进程,并且会引发一个PHP错误。

pcntl_waitpid

挂起当前进程的执行,直到参数pid指定的进程号对应的进程退出, 或接收到一个信号要求中断当前进程或调用一个信号处理函数。

如果pid指定的子进程在此函数调用时已经退出(僵尸进程),此函数将立刻返回。

语法:

int pcntl_waitpid ( int $pid , int &$status [, int $options = 0 ] )

返回值:

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

pcntl_wait

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

pcntl_wait 等同于以-1作为参数pid 的值并且没有options参数来调用pcntl_waitpid() 函数。

示例

多子进程实现并发

多子进程时,需要注意避免僵尸进程,浪费资源:

<?php

$procNum = 3;
for($i = 0; $i < $procNum; $i++){
$nPID = pcntl_fork();//创建子进程
if ($nPID == 0){
work();
exit(0);
} elseif ($nPID == -1) {
die('could not fork');
} else {
// 如果在这里写 pcntl_wait($status),则只有当前进程执行完毕后才会创建下一个进程
}
}
// 父进程会执行下面的代码,等待子进程执行完毕,避免僵尸进程
$n = 0;
while ($n < $procNum) {
$nStatus = -1;
$nPID = pcntl_wait($nStatus);
if ($nPID > 0) {
++$n;
}
} function work(){
while(true){
$nPID = pcntl_fork();//创建子进程
if ($nPID == 0){
echo time();
exit(0);
}
pcntl_waitpid($nPID,$nStatus);
}
}

进程状态:

[root@VM_139_38_centos ~]# ps -ef | grep php
root 26355 24175 0 23:17 pts/0 00:00:00 php pcntl2.php
root 26356 26355 3 23:17 pts/0 00:00:00 php pcntl2.php
root 26357 26355 5 23:17 pts/0 00:00:00 php pcntl2.php
root 26358 26355 3 23:17 pts/0 00:00:00 php pcntl2.php
root 27078 24819 0 23:17 pts/4 00:00:00 grep --color=auto php
root 27079 26357 0 23:17 pts/0 00:00:00 php pcntl2.php
root 27080 26358 0 23:17 pts/0 00:00:00 php pcntl2.php
root 27081 26356 0 23:17 pts/0 00:00:00 php pcntl2.php

单子进程

<?php

$pid = pcntl_fork();

if ($pid == -1) {
die('could not fork');
} elseif ($pid) {
pcntl_wait($status);
} else {
while(1) {
sleep(1);
echo time();
}
}

PHP 实现并发-进程控制 PCNTL的更多相关文章

  1. Linux C 程序 进程控制(17)

    进程控制 1.进程概述现代操作系统的特点在于程序的并行执行.Linux是一个多用户多任务的操作系统.ps .pstree 查看进程进程除了进程id外还有一些其他标识信息,可以通过相应的函数获得.// ...

  2. Linux Shell多进程并发以及并发数控制

    1. 基础知识准备 1.1. linux后台进程 Unix是一个多任务系统,允许多用户同时运行多个程序.shell的元字符&提供了在后台运行不需要键盘输入的程序的方法.输入命令后,其后紧跟&a ...

  3. linux 命令及进程控制

    main.c  main.o/main.obj  main/main.exe          编译                连接 程序运行;      两步: gcc/g++  -c  mai ...

  4. Linux网络编程学习(二) ----- 进程控制(第三章)

    1.进程和程序 程序是一个可执行文件,而一个进程是一个执行中的程序实例.一个进程对应于一个程序的执行,进程是动态的,程序是静态的,多个进程可以并发执行同一个程序.比如几个用户可以同时运行一个编辑程序, ...

  5. 进程控制(Note for apue and csapp)

    1. Introduction We now turn to the process control provided by the UNIX System. This includes the cr ...

  6. UNIX环境高级编程 第8章 进程控制

    本章是UNIX系统中进程控制原语,包括进程创建.执行新程序.进程终止,另外还会对进程的属性加以说明,包括进程ID.实际/有效用户ID. 进程标识 每个进程某一时刻在系统中都是独一无二的,它们之间是用一 ...

  7. Yuchuan_Linux_C 编程之十 进程及进程控制

    一.整体大纲 二.基础知识 1. 进程相关概念 1)程序和进程 程序,是指编译好的二进制文件,在磁盘上,不占用系统资源(cpu.内存.打开的文件.设备.锁....)     进程,是一个抽象的概念,与 ...

  8. 【av68676164(p18-p20)】进程控制

    4.2.1 进程控制的概念 进程控制的概念 在进程生存全期间,对其全部行为的控制 存在四个典型的控制行为 创建进程 阻塞进程 撤销进程 唤醒进程 进程创建 功能:创建一个具有制定标识(ID)的进程 参 ...

  9. Linux&c 文件操作,线程进程控制,网络编程,简单知识点梳理

    一:文件操作 在linux下,一切皆文件,目录是文件,称为目录文件,内容是该目录的目录项(但是目录只有内核可以编辑,超级用户也不可以编辑),设备也是设备文件,在/dev存放的就是一些设备文件,linu ...

随机推荐

  1. todo JVM笔记

    之前给自己定了很多计划,要学Dubbo,Netty,SSHM源码,Tomcat源码...这些基本浅尝辄止,很难继续研读,过不了多久就忘了. 觉得还是基础不够,所以决定把<JVM>.< ...

  2. AFNetworking2.0源码解析<三>

    本篇说说安全相关的AFSecurityPolicy模块,AFSecurityPolicy用于验证HTTPS请求的证书,先来看看HTTPS的原理和证书相关的几个问题. HTTPS HTTPS连接建立过程 ...

  3. DRF框架之视图类

    前后端分离的项目 >: pip3 install djangorestframework   一.视图类传递参数给序列化类 视图层:views.py 需求: (1)在视图类中实列化对象是,可以设 ...

  4. fpga配置方式 .jic固化为ps模式

    FPGA不同下载方式的区别[扫盲]以及如何利用AS模式固化程序(转载)     主动配置方式(AS)和被动配置方式(PS)和最常用的(JTAG)配置方式: AS由FPGA器件引导配置操作过程,它控制着 ...

  5. PCA 主成分分析

    链接1 链接2(原文地址) PCA的数学原理(转) PCA(Principal Component Analysis)是一种常用的数据分析方法.PCA通过线性变换将原始数据变换为一组各维度线性无关的表 ...

  6. centos7安装mxnet

    pip install mxnet-cu90 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com 安装sklearn时总报错 ...

  7. SpringBoot之集成数据库

    一.集成 MySQL 数据库 1.1 配置 MySQL 添加依赖 <dependencies> <!--Spring 数据库相关依赖--> <dependency> ...

  8. 去掉html中的标签

    //去掉html中的图片 String regEx_image = "(<img.*src\\s*=\\s*(.*?)[^>]*?>)"; Pattern p_s ...

  9. elementui多个文件上传问题

    我认为绑定一个值 然后把值改变不同的名字即可

  10. Linux学习-通过loganalyzer展示MySQL中rsyslog日志

    一.实验环境 系统:CentOS7.6 软件包:apache,php,mariadb-server (都是基于光盘yum源) 源码包:loganalyzer-4.1.7.tar.gz (http:// ...