Swoole 不支持信号驱动 I/O(SIGIO),其核心是基于 epoll/kqueue 的 I/O 多路复用事件驱动模型;所有网络事件均由 Reactor 线程通过 epoll_wait() 监听并分发回调,无任何 SIGIO 注册或 FIOASYNC 设置。

Swoole 不支持信号驱动 I/O(SIGIO),它只用 I/O 多路复用(epoll/kqueue)作为事件监听机制。 所有“Swoole 用 SIGIO”的说法都是误解,源码里找不到任何 sigaction、SIGIO 注册或 FIOASYNC 设置逻辑。
为什么有人误以为 Swoole 用了信号驱动 I/O
混淆通常来自术语泛化:把“事件通知”笼统叫成“信号”,但 Linux 中的 SIGIO 是一套特定机制——需对 fd 调用 fcntl(fd, F_SETOWN, getpid()) + fcntl(fd, F_SETFL, O_ASYNC),内核在 I/O 就绪时发信号给进程。Swoole 完全没走这条路。
-
SIGIO是异步通知,但不可靠(信号不排队、易丢失、难以关联具体 fd) - Swoole 的事件循环靠
epoll_wait()或kqueue()主动轮询就绪列表,精确、可扩展、无丢失 - 所有回调(如
onReceive、onConnect)都由 Reactor 线程从 epoll 返回的就绪事件中分发,不是信号中断触发
Swoole 的 I/O 多路复用实际怎么工作
以 ReactorEpoll 为例,核心就是标准 epoll 流程:
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 初始化时调用
epoll_create()创建实例,存入reactor_->native_handle - 每个新连接调用
epoll_ctl(EPOLL_CTL_ADD)注册EPOLLIN | EPOLLET - 主循环反复调用
epoll_wait()阻塞等待,返回就绪 fd 列表 - 遍历就绪事件,根据
e.data.ptr找到对应Socket*,再派发到注册的回调
整个过程不依赖信号,也不 fork 子进程或设 handler,纯用户态事件循环 + 内核就绪通知。
协程下看起来“像异步”但底层仍是多路复用
写 go function() { $mysql->query(...); } 时看似“发起即返回”,其实:
- 协程挂起后,控制权交还给 Swoole 协程调度器
- 调度器继续执行其他协程,或调用
epoll_wait()等待下一个 I/O 就绪 - 当 MySQL socket 可读时,epoll 返回,调度器唤醒对应协程继续执行
- 没有
signal、没有io_uring、也没有内核级 AIO,全是用户态协程 + epoll 驱动
真正容易被忽略的是:Swoole 的“异步感”完全来自协程封装和事件循环的配合,不是换了一套 I/O 模型。一旦你关掉协程(比如用 Swoole\Process 手动 fork),或者在协程外调用阻塞函数(如 sleep()、file_get_contents()),整个 Reactor 就会被卡住——这恰恰反向证明了它底层是单线程 + 多路复用,而非信号或真异步 I/O。


















