php中pcntl_fork详解
pcntl_fork()函数是php-pcntl模块中⽤于创建进程的函数。(不⽀持windows)
⾄于php_pcntl扩展如何安装开启这⾥就不介绍了,只分析pcntl_fork()这个函数本⾝。
1.$one = 123;
2.$one++;
3.$two = time();
4.$pid = [];
5.$pid = pcntl_fork();
6.$three = time();
当:pcntl_fork()函数执⾏的时候,会创建⼀个⼦进程。⼦进程会复制当前进程,也就是⽗进程的所有:数据,代码,还有状态。
1.当pcntl_fork()创建⼦进程成功后,在⽗进程内,返回0,在⼦进程内返回⾃⾝的进程号,失败则返回-1
2.⼦进程会复制⽗进程的代码,数据。那么就说明:⼦,⽗进程拥有的代码和数据会⼀模⼀样。
3.重点:⼦进程会复制⽗进程的状态,那么就有上⾯的⽰例代码:在第五⾏执⾏了pcntl_fork,那么创建出的⼦进程,代码也是从第五⾏开始执⾏的。⼜⼦进程复制了数据,代码。所以,在⼦进程内同理存在:$one,$two等变量
for ($i = 0; $i < 3; $i++) {
$pid = pcntl_fork();
}
sleep(30);
那么:上⾯的for循环,实际会产⽣多少个⼦进程?答案是7个,在linux下,⽤ps命令将可以看到8个进程(1个⽗进程,7个⼦进程)
原因:⽗进程在$i=0时,创建出⼀个⼦进程0,此时的⼦进程,还会继续执⾏循环。创建出属于⾃⼰的⼦进程。同理:$i=1时也会这样……参考:
PHP创建多进程的Demo⽰例:
<?php
/**
* PHP多进程和多线程的处理
*/
//创建socket监听
$socketserv = stream_socket_server('tcp://0.0.0.0:8000', $errno, $errstr);
//创建5个⼦进程
for ($i = 0; $i < 5; $i++) {
//使⽤pcntl_fork()创建进程,会返回pid,如果pid==0,则表⽰主进程
if (pcntl_fork() == 0) {
//循环监听
while (true) {
$conn = stream_socket_accept($socketserv);
//如果监听失败,则重新去监听
if(!$conn){
continue;
}
//读取流信息,读取的⼤⼩是9000
$request = fread($conn, 9000);
//写⼊响应
$response = 'hello';
fwrite($conn, $response);
//关闭流
fclose($conn);
}
//创建完所有的⼦进程,然后退出
php支持多线程吗
exit(0);
}
}
运⾏ php stream_socket.php,使⽤ps -ef 查看进程,会看到多出了如下的5个进程:
扩展:PHP的异步⾮阻塞模型 Reactor:
Reactor有4个核⼼的操作:
add 添加socket监听到reactor
set 修改事件监听,可以设置监听的类型,如可读、可写
del 从reactor中移除,不再监听事件
callback 就是事件发⽣后对应的处理逻辑,⼀般在add/set时制定。
(C语⾔⽤函数指针实现,JS可以⽤匿名函数,PHP可以⽤匿名函数、对象⽅法数组、字符串函数名)
Reactor只是⼀个事件发⽣器,实际对socket句柄的操作,如connect/accept、send/recv、close是在callback中完成的。具体编码可参考下⾯的代码(需要先安装Reactor扩展):
Reactor模型还可以与多进程、多线程结合起来⽤,既实现异步⾮阻塞IO,⼜利⽤到多核。
⽬前流⾏的异步服务器程序都是这样的⽅式:如
Nginx:多进程Reactor
Nginx+Lua:多进程Reactor+协程
Golang:单线程Reactor+多线程协程
Swoole:多线程Reactor+多进程Worker

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。