参考 基于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. JavaScript回顾

    JavaScript是Web编程语言. JavaScript是一种基于对象的脚本语言 它是解释执行的 在客户端的浏览器中运行 可以被嵌入HTML文件中 代码以纯文本的形式存储在文件中 可以使用任何一种 ...

  2. 机器学习-KNN算法详解与实战

    最邻近规则分类(K-Nearest Neighbor)KNN算法 1.综述 1.1 Cover和Hart在1968年提出了最初的邻近算法 1.2 分类(classification)算法 1.3 输入 ...

  3. 什么是CPC,CPA,CVR,CTR,ROI

    合格的网络营销人员都应该熟悉下面的常见英文缩写,这些都是我们必须知道的名词解释:CVR (Click Value Rate): 转化率,衡量CPA广告效果的指标CTR (Click Through R ...

  4. linux系统快速搭建ftp服务器——实现匿名用户和创建用户访问服务器

    一.准备工作: linux系统为CentOS Linux release 7.5.1804 (Core)  可以使用 lsb_release -a  命令查看 window系统中安装 SecureCR ...

  5. 安装了sql-alchemy但导入sql_alchemy时失败

    问题描述:按成flask-sqlalchemy成功了,但是项目导入flask_alchemy时出错 但是,发现在代码中还是导入不了 之后发现问题,到file->setting->proje ...

  6. 无法启动链接服务器"XXX DB Link"的 OLE DB 访问接口 "SQLNCLI11" 的嵌套事务。由于 XACT_ABORT 选项已设置为 OFF,因此必须使用嵌套事务。链接服务器"XXX DB Link"的 OLE DB 访问接口 "SQLNCLI11" 返回了消息"无法在此会话中启动更多的事务"。

    无法启动链接服务器"XXX DB Link"的 OLE DB 访问接口 "SQLNCLI11" 的嵌套事务.由于 XACT_ABORT 选项已设置为 OFF,因 ...

  7. 【hackerrank】Type of Triangle

    题目如下: Write a query identifying the type of each record in the TRIANGLES table using its three side ...

  8. Jion的应用

  9. Linux学习-NFS服务

    一.NFS服务相关介绍 1.NFS简介 NFS (Network File System) 网络文件系统,基于内核的文件系统.Sun公司开发,通过使用NFS,用户和程序可以像访问本地文件一样访问远端系 ...

  10. 在mac上安装rabbitmq

    在 OS X 上安装 RabbitMQ¶ 在 Snow Leopard 上安装 RabbitMQ 最简单的方式就是 Homebrew ——OS X 上的一款新颖别致,光彩动人的包管理系统. 在本例中, ...