浅析 PHP7 底层运行机制

PHP7 代码执行过程

PHP 是解释型语言,其执行过程需先编译成中间代码,再经由特定的虚拟机,翻译成特定的指令被执行。其执行过程如下:

PHP 代码 => Token => 抽象语法树 => Opcodes => 执行

各个步骤内容如下:

  • 源代码通过词法分析得到 Token

Token 是 PHP 代码被切割成的有意义的标识。PHP7 一共有 137 种 Token,在zend_language_parser.h 文件中做了定义。

  • 基于语法分析器将 Token 转换成抽象语法树(AST)

Token 就是一个个的词块,但是单独的词块不能表达完整的语义,还需要借助一定的规则进行组织串联。所以就需要语法分析器根据语法匹配Token,将 Token 进行串联。语法分析器串联完 Token 后的产物就是抽象语法树(AST,Abstract Syntax Tree)。
AST 是 PHP7 版本的新特性,之前版本的 PHP 代码的执行过程中是没有生成 AST 这一步的。它的作用主要是实现了PHP编译器和解释器的解耦,提升了可维护性。

  • 将语法树转换成 Opcode

需要将语法树转换成Opcode,才能被引擎直接执行。

  • 执行 Opcodes

opcodes 是 opcode 的集合形式,是 PHP 执行过程中的中间代码。PHP工程优化措施中有一个比较常见的“开启 opcache”,指的技术这里将 opcodes 进行缓存。通过省去从源码到 opcode 的阶段,引擎直接执行缓存好的 opacode,以提升性能。

PHP7 内核架构

要把这张图印在脑海里

  • zend引擎

词法/语法分析、AST编译和 opcodes 的执行均在 Zend 引擎中实现。此外,PHP的变量设计、内存管理、进程管理等也在引擎层实现。

  • PHP层

zend 引擎为 PHP 提供基础能力,而来自外部的交互则需要通过 PHP 层来处理。

  • SAPI

server API 的缩写,其中包含了场景的 cli SAPI 和 fpm SAPI。只要遵守定义好的 SAPI 协议,外部模块便可与PHP完成交互。

  • 扩展部分

依据 zend 引擎提供的核心能力和接口规范,可以进行开发扩展。

PHP 7 源码结构

php 7 的源码主要目录有:sapi 、Zend、main、ext 和 TSRM 这几个。

  • sapi目录

sapi目录是对输入和输出层的抽象,是PHP提供对外服务的规范。

几种常用的 SAPI:

1)apache2handler: Apache 扩展,编译后生成动态链接库,配置到Apache下。当有 http 请求到 Apache 时,根据配置会调用此动态链接库来执行PHP代码,完成与PHP的交互。

2)cgi-fcgi: 编译后生成支持 CGI 协议的可执行程序,webserver(如NGINX)通过 CGI 协议把请求传给CGI进程,CGI 进程根据请求执行相应代码后将执行结果返回给 webserver。

3)fpm-fcgi: fpm是 FastCGI 进程管理器。以 NGINX 服务器为例,当有请求发送到 NGINX 服务器,NGINX 按照 FastCGI 协议把请求交给 php-fpm 进程处理。

4)cli: PHP的命令行交互接口

  • Zend 目录

Zend 目录是 PHP 的核心代码。PHP中的内存管理,垃圾回收、进程管理、变量、数组实现等均在该目录的源码里。

  • main 目录

main目录是SAPI层和Zend层的黏合剂。Zend 层实现了 PHP 脚本的编译和执行,sapi 层实现了输入和输出的抽象,main目录则在它们中间起着承上启下的作用。承上,解析 SAPI 的请求,分析要执行的脚本文件和参数;启下,调用 zend 引擎之前,完成必要的模块初始化等工作。

  • ext目录

ext 是 PHP 扩展相关的目录,常用的 array、str、pdo 等系列函数都在这里定义。

  • TSRM

TSRM(Thread Safe Resource Manager)——线程安全资源管理器, 是用来保证资源共享的安全。

参考资料
《PHP7 底层设计与源码实现》

本作品采用《CC 协议》,转载必须注明作者和本文链接
You can not connect the dots looking forward, you can only connect them looking backwards.
本帖由系统于 4年前 自动加精
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 3

真的开始学习了呀! :+1:

PHP-CS-Fixer 的运行原理就是根据解释器解析出来的 Tokens 进行分析,然后再修改、增删一些 Token(例如添加空格、换行等),最后拼接成代码。

PHPStan 的原理类似,只不过它拿到的不是 Tokens 了,而是 AST。

4年前 评论
JeffreyC (楼主) 4年前

想和你们一起学习

4年前 评论
南城以南

现在想自己组个队 有没有想组队的?

4年前 评论
ninscious 4年前
jackbot 4年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!