PHP学习(二)PHP7的执行原理和内核架构
(PHP学习二)PHP7的执行原理一、理论概念二、代码说明1. Token2.AST(抽象语法树)一、理论概念首先进行词法分析,将源代码切割为多个字符串单元,分割后的字符串称为Token。该步骤的词法分析器使用Re2c实现。由于Token无法表达完整语义,故需要基于语法分析器将Token和符合文法规则的代码生成抽象语法树(也就是上一届最后说的 AST)。语法分析器基于Bison(一种通用解析器生成
(PHP学习二)执行原理
一、执行原理
(一)理论概念
- 首先进行词法分析,将源代码切割为多个字符串单元,分割后的字符串称为Token。
该步骤的词法分析器使用Re2c实现。 - 由于Token无法表达完整语义,故需要基于语法分析器将Token和符合文法规则的代码生成抽象语法树(也就是上一届最后说的 AST)。
语法分析器基于Bison(一种通用解析器生成器)实现,使用了链接: BNF(Backus-NaurForm 巴克斯范式).来表达文法规则,Bison借助状态机、状态转移表和压栈、出栈等一系列操作生成抽象语法树。 - 抽象语法树被转换为机器指令执行。这些指令称为opcode,这里可以理解为CPU指令。抽象语法树转换为opcode指令集合,PHP解释执行opcode。
这是来自知乎的一个简易流程说明。
[ PHP源码 ]
=> 词法分析 / 语法分析 -> [ 抽象语法树(AST) ]
=> 字节码编译器 -> [ Zend字节码(指令集为 Zend opcodes) ]
=> 字节码解释器 -> [ 程序运行结果 ]
(二) 代码说明
1. Token
# 在PHP中,提供了Token_get_all()这个函数来获取PHP代码被切割后的Token
php -r 'print_r(Token_get_all("<?php echo \"Hello World\";"));';
# 执行结果
Array
(
[0] => Array
(
[0] => 379 //每个成员数组的第一个值为Token对应的枚举值
[1] => <?php
[2] => 1
)
[1] => Array
(
[0] => 328
[1] => echo
[2] => 1
)
[2] => Array
(
[0] => 382
[1] =>
[2] => 1
)
[3] => Array
(
[0] => 323
[1] => "Hello World"
[2] => 1
)
[4] => ;
)
在输出的二维数组中,每个成员数组的第一个值为Token对应的枚举值。
字符串“<?php”切割后对应的Token值为379:源码【#define T_OPEN_TAG 379】
echo 对应的Token值为328:源码【#define T_ECHO 328】
空格 对应的Token值为382:源码【#define T_WHITESPACE】
字符串“Hello World” 对应的Token值为 323 源码 【#define T_CONSTANT_ENCAPSED_STRING】
2.AST(抽象语法树)
上面讲了Token,可以看出每个Token并不能表达出完整的语义,需要借助语法分析器依据规则进行组织串联,检查语法,匹配Token。
而php7组织串联的产物就是AST(Abstrat Syntax Tree),实现了PHP编译器和解释器解耦,提升了可维护性。
抽象语法树具有树状结构。
节点分为多种类型,对应着php的语法。
3.opcodes
AST扮演了源码到中间代码的临时存储介质的角色,还需将其转换为opcode才能被引擎直接执行。
opcode是单条指令,opcodes它的集合形式,是php执行过程的中间代码。
二、内核架构
(一)Zend引擎
词法语法分析、AST编译、opcodes的执行、PHP的变量设计、内存管理、进程管理等都在Zend引擎中实现。
(二)PHP层
Zend引擎为PHP提供方基础能力,PHP层主要处理来自外部的交互
(三)SAPI (Server API)
包含 cli SAPI和 fpm SAPI。
(四)扩展EXT
php主要包含源码目录:sapi、Zend、main、ext、TSRM
sapi
sapi目录是对输入和输出层的抽象,是PHP提供对外服务的规范。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)