php底层运行机制与原理详解

上传人:m**** 文档编号:53836148 上传时间:2018-09-05 格式:DOCX 页数:11 大小:143.53KB
返回 下载 相关 举报
php底层运行机制与原理详解_第1页
第1页 / 共11页
php底层运行机制与原理详解_第2页
第2页 / 共11页
php底层运行机制与原理详解_第3页
第3页 / 共11页
php底层运行机制与原理详解_第4页
第4页 / 共11页
php底层运行机制与原理详解_第5页
第5页 / 共11页
点击查看更多>>
资源描述

《php底层运行机制与原理详解》由会员分享,可在线阅读,更多相关《php底层运行机制与原理详解(11页珍藏版)》请在金锄头文库上搜索。

1、phpphp 底层运行机制与原理详解底层运行机制与原理详解1 PHP 的设计理念及特点多进程模型:由于 PHP 是多进程模型,不同请求间互不干涉,这样保证了一个请求挂掉不会对全盘服务造成影响,当然,时代发展,PHP 也早已支持多线程模型。弱类型语言:和 C/C+、Java、C#等语言不同,PHP 是一门弱类型语言。一个变量的类型并不是一开始就确定不变,运行中才会确定并可能发生隐式或显式的类型转换,这种机制的灵活性在 web 开发中非常方便、高效。引擎(Zend)+组件(ext)的模式,降低内部耦合。中间层(sapi),隔绝 web server 和 PHP。语法简单灵活,没有太多规范。2 PH

2、P 的核心架构PHP 核心架构如下图,从下到上可以简单分为四层体系:Zend 引擎:纯 C 实现,是 PHP 的内核部分,它将 PHP 代码翻译(词法、语法解析等一系列编译过程)为可执行 opcode 的处理并实现相应的处理方法、实现了基本的数据结构(如 hashtable、oo)、内存分配及管理、提供了相应的 api 方法供外部调用,是一切的核心,所有的外围功能均围绕 Zend 实现。金星棋牌 http:/Extensions:围绕着 Zend 引擎,extensions 通过组件式的方式提供各种基础服务,我们常见的各种内置函数(如 array 系列)、标准库等都是通过 extension

3、来实现。Sapi:全称是 Server Application Programming Interface 服务端应用编程接口,Sapi 通过一系列钩子函数,使得 PHP 可以和外围交互数据,这是 PHP 非常优雅和成功的一个设计,通过 sapi 成功的将 PHP 本身和上层应用解耦隔离,PHP 可以不再考虑如何针对不同应用进行兼容,而应用本身也可以针对自己的特点实现不同的处理方式。常见的一些 sapi 有:apache2handler:这是以 apache 作为 webserver,采用 mod_PHP 模式运行时候的处理方式,也是现在应用最广泛的一种。cgi:这是 webserver 和

4、PHP 直接的另一种交互方式,也就是大名鼎鼎的 fastcgi 协议,在最近今年 fastcgi+PHP 得到越来越多的应用,也是异步 webserver 所唯一支持的方式。cli:命令行调用的应用模式上层应用:这就是我们平时编写的 PHP 程序,通过不同的 sapi 方式得到各种各样的应用模式,如通过 webserver 实现 web 应用、在命令行下以脚本方式运行等。3 PHP 的执行流程PHP 实现了一个典型的动态语言执行过程:拿到一段代码后,经过词法解析、语法解析等阶段后,源程序会被翻译成一个个指令 (opcodes),然后 ZEND 虚拟机顺次执行这些指令完成操作。PHP 本身是用

5、C 实现的,因此最终调用的也都是 C 的函数,实际上,可以把PHP 看成是一个 C 开发的软件。天地棋牌 http:/PHP 的执行的核心是翻译出来的一条一条指令,也即 opcode。Opcode 是 PHP 程序执行的最基本单位。一个 opcode 由两个参数(op1,op2)、返回值和处理函数组成。PHP 程序最终被翻译为一组 opcode 处理函数的顺序执行。常见的几个处理函数:ZEND_ASSIGN_SPEC_CV_CV_HANDLER : 变量分配 ( a=b)ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER:函数调用ZEND_CONCAT_SPEC_CV_CV_

6、HANDLER:字符串拼接 a.bZEND_ADD_SPEC_CV_CONST_HANDLER: 加法运算 a+2ZEND_IS_EQUAL_SPEC_CV_CONST:判断相等 a=1ZEND_IS_IDENTICAL_SPEC_CV_CONST:判断相等 a=14 Zend 引擎介绍Zend 引擎作为 PHP 的内核,有很多经典的设计机制,主要有以下几个:4.1 实现 HashTable 数据机构:HashTable 是 Zend 的核心数据结构。在 PHP 里面几乎用来实现所有常见功能,我们知道的 PHP 数组即是其典型应用,此外,在 zend 内部,如函数符号表、全局变量等也都是基于

7、hash table 来实现。Zend hash table 实现了典型的 hash 表散列结构,同时通过附加一个双向链表,提供了正向、反向遍历数组的功能。其结构如下图可以看到,在 hash table 中既有 key-value 形式的散列结构,也有双向链表模式,使得它能够非常方便的支持快速查找和线性遍历。散列结构:Zend 的散列结构是典型的 hash 表模型,通过链表的方式来解决冲突。需要注意的是 zend 的 hash table 是一个自增长的数据结构,当 hash 表数目满了之后,其本身会动态以 2 倍的方式扩容并重新元素位置。初始大小均为 8。另外,在进行 key-value快速

8、查找时候,zend 本身还做了一些优化,通过空间换时间的方式加快速度。比如在每个元素中都会用一个变量 nKeyLength 标识 key 的长度以作快速判定。双向链表:Zend hash table 通过一个链表结构,实现了元素的线性遍历。理论上,做遍历使用单向链表就够了,之所以使用双向链表,主要目的是为了快速删除,避免遍历。Zend hash table 是一种复合型的结构,作为数组使用时,即支持常见的关联数组也能够作为顺序索引数字来使用,甚至允许 2 者的混合。PHP 关联数组:关联数组是典型的 hash_table 应用。一次查询过程经过如下几步(从代码可以看出,这是一个常见的 hash

9、 查询过程并增加一些快速判定加速查找):01 getKeyHashValue h;02 index = n 03 Bucket *p = arBucketindex;04 while (p) 05 if (p-h = h) 07 08 p=p-next;09 10 RETURN FALTURE;PHP 索引数组:索引数组就是我们常见的数组,通过下标访问。例如 arr0,Zend HashTable 内部进行了归一化处理,对于 index 类型 key 同样分配了 hash 值和nKeyLength(为 0)。内部成员变量 nNextFreeElement 就是当前分配到的最大 id,每次pus

10、h 后自动加一。正是这种归一化处理,PHP 才能够实现关联和非关联的混合。由于 push操作的特殊性,索引 key 在 PHP 数组中先后顺序并不是通过下标大小来决定,而是由 push的先后决定。例如 arr1 = 2; arr2 = 3;对于 double 类型的 key,Zend HashTable 会将他当做索引 key 处理 移动电玩城 http:/om4.2 PHP 变量实现原理:PHP 是一门弱类型语言,不严格区分变量的类型。PHP 在变量申明的时候不需要指定类型。PHP 在程序运行期间可能进行变量类型的隐示 转换。 和其他强类型语言一样,程序中也可以进行显示的类型转换。PHP 变

11、量可以分为简单类型(int、string、bool)、集合类型(array 、resource 、object)和常量(const)。以上所有的变量在底层都是同一种结构zval。Zval 是 zend 中另一个非常重要的数据结构,用来标识并实现 PHP 变量,其数据结构如下:Zval 结构体主要由三部分组成:type:指定了变量所述的类型(整数、字符串、数组等)refcount strB = 456; intA=123; intB=456;现在对如下的几种字符串拼接方式做一个比较和说明:1 res = strA.strB 和 res = “strAstrB”这种情况下,zend 会重新 mal

12、loc 一块内存并进行相应处理,其速度一般。2 strA = strA.strB这种是速度最快的,zend 会在当前 strA 基础上直接 relloc,避免重复拷贝3 res = intA.intB这种速度较慢,因为需要做隐式的格式转换,实际编写程序中也应该注意尽量避免4 strA = sprintf (“%s%s”,strA,strB);这会是最慢的一种方式,因为 sprintf 在 PHP 中并不是一个语言结构,本身对于格式识别和处理就需要耗费比较多时间,另外本身机制也是 malloc。不过 sprintf 的方式最具可读性,实际中可以根据具体情况灵活选择。4.2.3 数组变量PHP 的

13、数组通过 Zend HashTable 来天然实现。foreach 操作如何实现对一个数组的 foreach 就是通过遍历 hashtable 中的双向链表完成。对于索引数组,通过 foreach 遍 历效率比 for 高很多,省去了 key-value 的查找。count 操作直接调用 HashTable-NumOfElements,O(1)操作。对于123这样的字符串,zend 会转换为其整数形 式。arr123和 arr123是等价的4.2.4 资源变量资源类型变量是 PHP 中最复杂的一种变量,也是一种复合型结构。PHP 的 zval 可以表示广泛的数据类型,但是对于自定义的数据类型却

14、很难充分描述。由于没有有效的方式描绘这些复合结构,因此也没有办法对它们使用传统的操作符。要解决这个问题,只需要通过一个本质上任意的标识符(label)引用指针,这种方式被称为资源。在 zval 中,对于 resource,lval 作为指针来使用,直接指向资源所在的地址。Resource 可以是任意的复合结构,我们熟悉的 mysqli、fsock、memcached 等都是资源。如何使用资源:1 注册:对于一个自定义的数据类型,要想将它作为资源。首先需要进行注册,zend会为它分配全局唯一标示。2 获取一个资源变量:对于资源,zend 维护了一个 id-实际数据的 hash_tale。对于一个

15、 resource,在 zval 中只记录了它的 id。fetch 的时候通过 id 在 hash_table 中找到具体的值返回。3 资源销毁:资源的数据类型是多种多样的。Zend 本身没有办法销毁它。因此需要用户在注册资源的时候提供销毁函数。当 unset 资源时,zend 调用相应的函数完成析构。同时从全局资源表中删除它。资源可以长期驻留,不只是在所有引用它的变量超出作用域之后,甚至是在一个请求结束并且新的请求产生之后。这些资源称为持久资源,因为它们贯通 SAPI 的整个生命周期持续存在,除非特意销毁。很多情况下,持久化资源可以在一定程度上提高性能。比如我们常见的 mysql_pconn

16、ect ,持久化资源通过 pemalloc 分配内存,这样在请求结束的时候不会释放。 对 zend 来说,对两者本身并不区分。4-3 . PHP 变量管理引用计数和写时拷贝:引用计数在内存回收、字符串操作等地方使用非常广泛。Zval 的引用计数通过成员变量 is_ref 和 ref_count 实现,通过引用计数,多个变量可以共享同一份数据。避免频繁拷贝带来的大量消耗。在进行赋值操作时,zend 将变量指向相同的 zval 同时 ref_count+,在 unset 操作时,对应的 ref_count-1。只有 ref_count 减为 0 时才会真正执行销毁操作。如果是引用赋值,则 zend 会修改 is_ref 为 1。PHP 变量通过引用计数实现变量共享数据,那如果改变其中一个变量值呢当试图写入一个变量时,Zend 若发现该变量指向的 zval 被多个变量共享,则为其复制一份 ref_count为 1 的 zval

展开阅读全文
相关资源
相关搜索

当前位置:首页 > IT计算机/网络 > PHP资料

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号