PHP底层运行机制与原理
文章目录
PHP设计理念及特点
- 多进程模型:不同请求之间,互补干涉,保证一个请求挂掉不会影响整体服务。
- 弱类型语言:变量类型并不是一开始就确当不变,运行中才会确定并可能发生隐式或显示的类型转换。web开发方便、高效。
- 引擎(Zend)+ 组件(ext)的模式,降低内部耦合。
- 中间层(sapi),隔绝web server 和 php。
PHP核心架构
从上到下四层体系
-
Zend引擎:PHP内核部分,将PHP代码翻译(词法、语法解析)为可执行opcode的处理并实现相应的处理方法、实现基本数据接口(hashtable、oo) 、内存分配及管理、提供了相应的API方法供外部调用,是一切的核心,所有外围功能围绕Zend实现。
-
Extension:围绕Zend引擎,通过组件方式提供各种基础服务,常见的各种内置函数、标准库都是通过extension来实现。
-
SAPI:全称是Server Application Programming Interface服务端应用编程接口,SAPI通过一系列钩子函数,使得PHP可以和外围交互数据。 SAPI将PHP本身和上层应用解耦隔离,PHP可以不用考虑如何针对不同应用进行兼容,而应用本身也可以针对自己的特点实现不同的处理方式。
- apache2handler:以apache作为webserver,采用mod_PHP模式运行时候的处理方式。
- cgi:webserver和PHP直接的另一种交互方式,fastcgi协议,也是异步webserver所唯一支持的方式。
- cli:命令行调用模式。
-
上层应用:编写的PHP程序,通过不同的SAPI方式得到各种各样的应用模式。
PHP执行流程
PHP实现了一个典型的动态语言执行过程:拿到一段代码后,经过词法分析、语法解析等阶段后, 源程序会被翻译成一个个指令(opcodes),然后ZEND虚拟机顺序执行这些指令完成操作。
执行的核心是opcode指令。opcode是PHP程序执行最基本的单位
ZEND 引擎介绍
Zend引擎作为PHP内核,经典设计机制介绍:
- 实现hashTable数据结构
- 数组
- 函数符号表、全部变量基于hashTable来实现
- 双向链表,提供正向、反向遍历数组的功能
- 散列结构,典型的hash表模型
- 通过链表别的方式来解决冲突
- hash表数目满了,本身以2倍的方式扩容
- 双向链表
- Zend hash table 通过一个链表结构,实现元素的线性遍历
- 不使用单向链表,目的就是快速删除,避免遍历
- 关联数组
- hashTable应用
- nKeyLength标识key长度来快速判定,空间换时间,
key->value
快速查找时
PHP变量实现原理
PHP变量管理-引用计数和写时拷贝
在进行赋值操作时,zend将变量指向相同的zval同时ref_count++
,在unset操作时,对应的ref_count-1
。只有ref_count
减为0时才会真正执行销毁操作。
如果是引用赋值,则zend会修改is_ref
为1。
PHP局部变量和全局变量的实现
两个符号表(symbol_table和 active_symbol_table),其中前者用来维护全局变量。后者是一个指针,指向当前活动的变量符号表,当程序进入到某个函数中时, zend 就会为它分配一个符号表x同时将active_symbol_table指向a。通过这样的方式实现全局、局部变量的区分。
获取变量值:PHP的符号表是通过hash_table实现的,对于每个变量都分配唯一标识,获取的时候根据标识从表中找到相应zval返回。
函数中使用全局变量:在函数中,我们可以通过显式申明global来使用全局变量。在active_symbol_table中创建symbol_table中同名变量的引用(引用变量的值要更新大家会一起更新),如果symbol_table中没有同名变量则会先创建。
参考
文章作者 小叨
上次更新 2020-06-04