一句话总纲:Zend Engine 就是PHP的虚拟机。把PHP源码编译成Zend中间字节码(OPcode),然后在虚拟机里逐条解释执行OPcode;负责内存管理、变量处理、函数调用、对象、异常,连接扩展,最终调用操作系统系统调用。
区分清楚:
PHP语言 = PHP语法 + Zend虚拟机。
浏览器看不懂PHP,操作系统也看不懂PHP源码;Zend Engine就是中间翻译+执行的核心。
一、根因:为什么需要Zend Engine?
PHP是解释型脚本语言,不能直接交给CPU执行。CPU只认二进制机器码。
方案分两步:
- 编译阶段:把人类写的PHP源码,编译为虚拟机指令OPcode(字节码);
- 执行阶段:Zend虚拟机,逐条跑OPcode。
好处:
- 源码不用每次都做完整词法语法解析;
- 可以用OPcache缓存字节码,跳过重复编译,大幅提速;
- Zend统一管理内存、对象、数组、引用计数;
- 提供扩展机制(Redis、PDO、Swoole/Hyperf)。
二、核心术语大全
- Zend Engine:PHP虚拟机,负责编译+执行PHP代码。PHP7/8使用Zend Engine 3/4。
- 词法分析(Lex):切分源码,分出关键字、变量名、字符串、运算符,产出Token令牌。
- 语法分析(Yacc):把Token组装成语法树AST(抽象语法树)。
- AST 抽象语法树:源码的结构化树形表示,PHP7之后引入。
- OPcode(操作码/字节码):Zend虚拟机的指令,不是CPU机器码,是虚拟机指令。类似Java的bytecode。
- OPcache:缓存编译后的OPcode。省去每次请求重复做词法、语法、AST编译。FPM/CLI必备。
- ZVM Zend Virtual Machine:Zend虚拟机,逐条执行OPcode。
- zval:前面讲过,所有PHP变量底层载体,ZVM操作的基本数据单元。
- 符号表(HashTable):PHP数组、对象属性、全局变量表底层都是HashTable哈希表。
- 执行栈(Zend VM Stack):虚拟机栈,用于函数调用、OPcode运算临时存放数据,区别于操作系统CPU栈。
- 扩展模块:C写的扩展,挂载到Zend引擎。Swoole、Redis、PDO都是扩展,向Zend新增函数/类。
- 处理函数调用、类、对象、异常、垃圾回收,全部由Zend引擎提供能力。
三、完整执行流程
<?php$a=1+2;echo$a;?>阶段1:词法分析
读取源码文本,切割成Token:<?php、$a、=、1、+、2、;、echo。
阶段2:语法分析,生成AST抽象语法树
校验语法是否合法;如果少分号、括号不匹配,这里报语法错误。
生成树形结构,描述代码逻辑:赋值表达式、加法表达式、echo输出。
阶段3:AST编译,生成OPcode字节码
遍历AST,翻译成Zend虚拟机指令OPcode。示例伪OPcode:
ASSIGN $a, ADD(1,2) ECHO $aOPcode不是给CPU跑,是给ZVM跑。
开启OPcache后:第一次编译后OPcode存入共享内存;后续请求直接读取OPcode,跳过词法语法AST,节省大量CPU。
阶段4:ZVM虚拟机逐条执行OPcode
ZVM有指令指针,指向当前OPcode:
- 执行ADD:取出两个数字运算,生成zval;
- 执行ASSIGN:把结果存入符号表变量$a;
- 执行ECHO:调用内部输出函数;底层会走系统调用write输出。
阶段5:执行结束
回收虚拟机栈;FPM模式下请求结束清理变量;CLI长进程(Hyperf)不会自动清空。
四、ZVM虚拟机执行模型
Zend VM 是栈式虚拟机。
运算依赖虚拟机栈:运算时把操作数压栈,执行OP,结果压回栈。
和CPU流水线完全两码事:CPU是硬件寄存器模型;ZVM是软件层面栈虚拟机。
五、Zend Engine 承担的六大核心工作
- 编译管线:词法 → 语法AST → OPcode字节码;OPcache缓存字节码。
- 虚拟机执行:解释执行OPcode,控制代码流程(if、for、函数、类方法)。
- 内存管理 ZMM:分配zval、字符串、数组、对象;引用计数+GC循环回收。
- HashTable哈希表:实现数组、变量符号表、对象属性。PHP数组本质是有序哈希表。
- 面向对象支持:类、实例对象、继承、访问控制、魔术方法。
- 扩展调度:PHP代码调用
redis->get()这类函数,Zend转发到C扩展,扩展再调用操作系统API。
六、两种运行模式差异(Hyperf重点)
FPM 短请求模式
每一次HTTP请求,走完整编译+执行(OPcache缓存OPcode);请求结束,本次请求的变量内存批量回收。进程保留,等待下一个请求。CLI常驻模式(Hyperf/Swoole)
进程启动后长期存活;脚本一次性加载编译,OPcode常驻内存;不会自动清空全局变量、静态变量,要手动处理,警惕内存泄漏。
七、常见误区
❌误区:PHP是纯解释语言,每次运行都逐行解析文本。
错。PHP7+有AST,编译为OPcode,OPcache缓存字节码,不是逐行文本解析。
❌误区:OPcode = CPU机器码
错。OPcode是Zend虚拟机指令,只能被ZVM解释,CPU不能直接执行OPcode。
❌误区:Zend Engine = PHP全部
错。Zend是虚拟机内核;除此之外还有标准库、各类扩展。
Zend Engine是PHP的虚拟机。执行流程:源码→词法分析生成Token→语法分析生成AST抽象语法树→编译生成OPcode字节码,ZVM栈虚拟机逐条执行OPcode。OPcache缓存OPcode,避免重复编译。
Zend引擎内置ZMM内存管理器、HashTable、面向对象、函数调度,支持C扩展。FPM是短请求,CLI(Hyperf)为常驻长进程,内存不会随请求自动释放。