初探PHP多进程
h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h4:first-child, body>h5:first-child, body>h6:first-child {
margin-top: 0;
padding-top: 0;
}
a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
margin-top: 0;
padding-top: 0;
}
h1+p, h2+p, h3+p, h4+p, h5+p, h6+p {
margin-top: 10px;
}
/* LINKS
=============================================================================*/
a {
color: #4183C4;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
/* LISTS
=============================================================================*/
ul, ol {
padding-left: 30px;
}
ul li > :first-child,
ol li > :first-child,
ul li ul:first-of-type,
ol li ol:first-of-type,
ul li ol:first-of-type,
ol li ul:first-of-type {
margin-top: 0px;
}
ul ul, ul ol, ol ol, ol ul {
margin-bottom: 0;
}
dl {
padding: 0;
}
dl dt {
font-size: 14px;
font-weight: bold;
font-style: italic;
padding: 0;
margin: 15px 0 5px;
}
dl dt:first-child {
padding: 0;
}
dl dt>:first-child {
margin-top: 0px;
}
dl dt>:last-child {
margin-bottom: 0px;
}
dl dd {
margin: 0 0 15px;
padding: 0 15px;
}
dl dd>:first-child {
margin-top: 0px;
}
dl dd>:last-child {
margin-bottom: 0px;
}
/* CODE
=============================================================================*/
pre, code, tt {
font-size: 12px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
code, tt {
margin: 0 0px;
padding: 0px 0px;
white-space: nowrap;
border: 1px solid #eaeaea;
background-color: #f8f8f8;
border-radius: 3px;
}
pre>code {
margin: 0;
padding: 0;
white-space: pre;
border: none;
background: transparent;
}
pre {
background-color: #f8f8f8;
border: 1px solid #ccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px;
}
pre code, pre tt {
background-color: transparent;
border: none;
}
kbd {
-moz-border-bottom-colors: none;
-moz-border-left-colors: none;
-moz-border-right-colors: none;
-moz-border-top-colors: none;
background-color: #DDDDDD;
background-image: linear-gradient(#F1F1F1, #DDDDDD);
background-repeat: repeat-x;
border-color: #DDDDDD #CCCCCC #CCCCCC #DDDDDD;
border-image: none;
border-radius: 2px 2px 2px 2px;
border-style: solid;
border-width: 1px;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
line-height: 10px;
padding: 1px 4px;
}
/* QUOTES
=============================================================================*/
blockquote {
border-left: 4px solid #DDD;
padding: 0 15px;
color: #777;
}
blockquote>:first-child {
margin-top: 0px;
}
blockquote>:last-child {
margin-bottom: 0px;
}
/* HORIZONTAL RULES
=============================================================================*/
hr {
clear: both;
margin: 15px 0;
height: 0px;
overflow: hidden;
border: none;
background: transparent;
border-bottom: 4px solid #ddd;
padding: 0;
}
/* TABLES
=============================================================================*/
table th {
font-weight: bold;
}
table th, table td {
border: 1px solid #ccc;
padding: 6px 13px;
}
table tr {
border-top: 1px solid #ccc;
background-color: #fff;
}
table tr:nth-child(2n) {
background-color: #f8f8f8;
}
/* IMAGES
=============================================================================*/
img {
max-width: 100%
}
-->
准备
我们都知道PHP是单进程执行的,PHP处理多并发主要是依赖服务器或PHP-FPM的多进程及它们进程的复用,但PHP实现多进程也意义重大,尤其是在后台Cli模式下处理大量数据或运行后台DEMON守护进程时,多进程的优势不用多说。
PHP的多线程也曾被人提及,但进程内多线程资源共享和分配的问题难以解决。PHP也有多线程想关的扩展 pthreads ,但据说不太稳定,且要求环境为线程安全,所用不多。
以前PHP群里的一位大神曾指导说后台PHP想进阶必然避不开多进程,正好公司里的守护进程也应用了PHP的多进程,结合着谷哥的各种资料和手册,总算理解了多进程,并自己写了一个小demo(在linux系统上实现的),用此文总结一下,如有错漏,谢谢提出。
要实现PHP的多进程,我们需要两个扩展 pcntl和 posix,安装方法这里不再赘述。
创建子进程
创建PHP子进程是多进程的开始,我们需要pcntl_fork()
函数;
fork函数详解
pcntl_fork() — 在当前进程当前位置产生分支(子进程)。此函数创建了一个新的子进程后,子进程会继承父进程当前的上下文,和父进程一样从pcntl_fork()函数处继续向下执行,只是获取到的pcntl_fork()的返回值不同,我们便能从判断返回值来区分父进程和子进程,分配父进程和子进程去做不同的逻辑处理。
pcntl_fork()函数成功执行时会在父进程返回子进程的进程id(pid),因为系统的初始进程init进程的pid为1,后来产生进程的pid都会大于此进程,所以我们可以通过判断pcntl_fork()的返回值大于1来确实当前进程是父进程;
而在子进程中,此函数的返回值会是固定值0,我们也可以通过判断pcntl_fork()的返回值为0来确定子进程;
而pcntl_fork()函数在执行失败时,会在父进程返回-1,当然也不会有子进程产生。
fork进程实例
以下是fork子进程的一个简单的小例子:
$ppid = posix_getpid();
$pid = pcntl_fork();
if ($pid == -1) {
throw new Exception('fork子进程失败!');
} elseif ($pid > 0) {
cli_set_process_title("我是父进程,我的进程id是{$ppid}.");
sleep(30); // 保持30秒,确保能被ps查到
} else {
$cpid = posix_getpid();
cli_set_process_title("我是{$ppid}的子进程,我的进程id是{$cpid}.");
sleep(30);
}
这时介绍一下两个函数:
posix_getpid()
:获取当前进程的pid;
cli_set_process_title('响亮的名字')
:为当前进程取一个响亮的名字。
运行这个例子,我们便能看到当前两个PHP进程了。
管理子进程
创建好了进程,那么怎么对子进程进行管理呢?使用信号。
在计算机科学中,信号是Unix、类Unix以及其他POSIX兼容的操作系统中进程间通讯的一种有限制的方式。它是一种异步的通知机制,用来提醒进程一个事件已经发生。
分发信号处理器
我们通过在父进程接收子进程传来的信号,判断子进程状态,来对子进程进行管理。
我们需要在父进程里使用pcntl_signal()
函数和pcntl_signal_dispatch()
函数来给各个子进程安装信号处理器。
pcntl_signal (int $signo , callback $handler) 安装一个信号处理器;
$signo是待处理的信号常量,callback是其处理函数
pcntl_signal_dispatch () 调用每个等待信号通过pcntl_signal()安装的处理器
PHP内常见的信号常量有:
SIGCHLD 子进程退出成为僵尸进程会向父进程发送此信号
SIGHUP 进程挂起
SIGTEM 进程终止
... // 其他请在手册中查看
安装并调用信号处理器后,一旦子进程有相应的信号返回给父进程,父进程就可以调用相应的callback函数对子进程处理;
处理子进程
对子进程的处理方法有:
posix_kill()
:此函数并不能顾名思义,它通过向子进程发送一个信号来操作子进程,在需要要时可以选择给子进程发送进程终止信号来终止子进程;
pcntl_waitpid()
:等待或返回fork的子进程状态,如果指定的子进程在此函数调用时已经退出(俗称僵尸进程),此函数将立刻返回,并释放子进程的所有系统资源,此进程可以避免子进程变成僵尸进程,造成系统资源浪费;
下面是两个函数的函数原型:
bool posix_kill ( int $pid , int $sig ) // 向进程id为$pid的进程发送$sig信号,$sig常见信号如上;
int pcntl_waitpid ( int $pid , int &$status [, int $options = 0 ] ) // 挂起当前进程的执行直到进程号为$pid的进程退出(如果$pid为-1,则等待任意一个子进程);
总结
这就是PHP多进程的基础使用了,感兴趣的可以自己写一个demo试一试手了。
最后贴一下鸟哥所说的PHP多进程优点:
- 使用多进程, 子进程结束以后, 内核会负责回收资源
- 使用多进程,子进程异常退出不会导致整个进程Thread退出. 父进程还有机会重建流程.
- 一个常驻主进程, 只负责任务分发, 逻辑更清楚.
对了,还有一个实例,改日上传到github,欢迎大家关注 >> 枕边书。
参考资料:
初探PHP多进程的更多相关文章
- PHP多进程初探 --- 利用多进程开发点儿东西吧
[原文地址:https://blog.ti-node.com/blog...] 干巴巴地叨逼叨了这么久,时候表演真正的技术了! 做个高端点儿的玩意吧,加入我们要做一个任务系统,这个系统可以在后台帮我们 ...
- PHP 多进程下载必应壁纸
手里拿着锤子,看什么都像是钉子 在放假的这几天,断断续续的看了老李关于 PHP 多进程的文章. PHP多进程初探 --- 开篇 PHP多进程初探 --- 孤儿和僵尸 PHP多进程初探 --- 信号 P ...
- 网页实时聊天之PHP实现websocket
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...
- Linux - 请允许我静静地后台运行
h1,h2,h3,h4,h5,h6,p,blockquote { margin: 0; padding: 0 } body { font-family: "Helvetica Neue&qu ...
- php websocket-网页实时聊天之PHP实现websocket(ajax长轮询和websocket都可以时间网络聊天室)
php websocket-网页实时聊天之PHP实现websocket(ajax长轮询和websocket都可以时间网络聊天室) 一.总结 1.ajax长轮询和websocket都可以时间网络聊天室 ...
- 网页实时聊天之PHP如何实现websocket
网页实时聊天之PHP如何实现websocket 一.总结 一句话总结: 应用 PHP 的 socket 函数库:PHP 的 socket 函数库跟 C 语言的 socket 函数非常类似 PHP 实现 ...
- 【10】Python urllib、编码解码、requests、多线程、多进程、unittest初探、__file__、jsonpath
1 urllib urllib是一个标准模块,直接import就可以使用 1.1get请求 from urllib.request import urlopen url='http://www.nnz ...
- pyrhon多进程操作初探
linux系统中提供了fork函数进行进程的创建,这个接口在函数返回上比较特殊,有两个返回值,一个是子进程返回值为0,一个是父进程返回值,值大于0,表是子进程的ID.如果小于0.则表示接口出错. py ...
- PHP7 网络编程(一)多进程初探
准备 我们都知道PHP是单进程执行的,PHP处理多并发主要是依赖服务器或PHP-FPM的多进程及它们进程的复用,但PHP实现多进程也意义重大,尤其是在后台Cli模式下处理大量数据或运行后台DEMON守 ...
随机推荐
- PHP连接SQL Server相关配置及说明
关于php怎么连接数据库,大家肯定有不同的看法,有的用wamp,有的用xamp,他们都是集成环境,方便操作.但有时,数据库的类型不同,要连接不同的数据库.今天和大家分享一下如何连接sql2000,服 ...
- ThinkPHP学习(二)
开发规范 1.命名规范 使用ThinkPHP开发的过程中应该尽量遵循下列命名规范: 特例:在ThinkPHP里面,有一个函数命名的特例,就是单字母大写函数,这类函数通常是某些操作的快 捷定义,或者有特 ...
- 【原创】轻量级移动设备即时通讯技术MobileIMSDK的常见问题解答
申明:MobileIMSDK 目前为个人原创开源工程且已发布,现整理了一些有关MobileIMSDK的常见的问题,希望对需要的人有用,谢谢.如需与作者交流,见文章底部个人签名处,互相学习. Mobil ...
- Android之自定义ViewPager实现图片的无线轮播
PS:以前也写过关于图片轮播这一块的博客.不过写的很烂,并且很多情况没有考虑到(没有支持无线轮播,和手势点击事件).因此这里写一篇补上.也是当时太年轻了. 注:图片请放大后再看.否则看不清楚. 学习内 ...
- mysql创建定时执行存储过程任务
sql语法很多,是一门完整语言.这里仅仅实现一个功能,不做深入研究. 目标:定时更新表或者清空表. 案例:曾经做过定时清空位置信息表的任务.(然而,当时并未考虑服务器挂掉后的情况) 本次测试:每5s更 ...
- asp.net 验证控件
前台文件 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1. ...
- C# 将DataTable数据源转换成实体类
using System; using System.Collections.Generic; using System.Data; using System.Reflection; /// < ...
- 使用VS Code开发 调试.NET Core 应用程序
使用VS Code开发 调试.NET Core RC2应用程序,由于.NET Core 目前还处于预览版. 本文使用微软提供的示例进行开发及调试. https://github.com/aspnet/ ...
- C#怎样保证弹出窗体是唯一并居中显示
Winform窗体中,假如我从Form1窗体要弹出Form2窗体,写法是这样的: Form2 f2 = new Form2(); f2.Show(); 1.如何使窗体打开时居中显示 //初始化默认窗体 ...
- 使用T4模板合并js文件
不知道该怎么表达,或许直接贴图贴代码更好 前因:在第一个使用angularjs的项目中我将所有的controller写到一个文件里面,深知维护起来那滋味,所以再次使用angularjs的时候,我便把所 ...