参考文献
5种IO模型:https://blog.mailjob.net/posts/3565199751.html
github代码下载:https://github.com/mailjobblog/dev_php_io/tree/master/test/signal
快速了解信号驱动io:https://www.itzhai.com/articles/it-seems-not-so-perfect-signal-driven-io.html
Linux 信号列表:https://wiki.swoole.com/#/other/signal
安装信号处理器函数(pcntl_signal):https://www.php.net/manual/zh/function.pcntl-signal.php
向进程发送信号函数(posix_kill):https://www.php.net/manual/zh/function.posix-kill.php
调用等待信号的处理器函数(pcntl_signal_dispatch):https://www.php.net/manual/zh/function.pcntl-signal-dispatch.php
获取进程的 PID 函数(posix_getpid):https://www.php.net/manual/zh/function.posix-getpid.php
信号驱动IO原理
所谓信号驱动式I/O(signal-driven I/O),就是预先告知内核,当某个描述符准备发生某件事情的时候,让内核发送一个信号通知应用进程。
主要的实现:
- Berkeley的实现使用
SIGIO
信号支持套接字和终端设备上的信号驱动式I/O; - SVR4使用SIGPOLL信号支持流设备上的信号驱动。
SIGPOLL等价于SIGIO。
通过UDP的recvfrom()
函数演示其工作原理如下图所示:
系统注册了ISGIO信号处理函数,并且启动了信号驱动式IO后,就可以继续执行程序了,等到数据报准备好之后,内核会发送一个SIGIO信号给应用进程,然后应用进程在信号处理函数中调用recvfrom读取数据报。
这种模型在内核等待数据报达到期间进程不会被阻塞,可以继续执行。
代码示例
server.php
<?php
require_once __DIR__."/../../vendor/autoload.php";
use DevPhpIO\Signal\Worker;
$server = new Worker('0.0.0.0', 9500);
$server->on('connect', function($server, $client){
dd($client, "客户端成功建立连接");
});
$server->on('receive', function(Worker $server, $client, $data){
dd($data, "处理client的数据");
$server->send($client, "hello i’m is server");
// $server->close($client);
});
$server->on('close', function($server, $client){
dd($client, "连接断开");
});
$server->start();
client.php
<?php
require_once __DIR__."/../../vendor/autoload.php";
// 连接服务端
$fp = stream_socket_client("tcp://127.0.0.1:9500");
fwrite($fp, "hello world lalala");
dd(fread($fp, 65535));
演示截图