探究PHP底层

探究PHP底层

1、PHP是什么?

PHP 指的是我们从外面看到的一套完整的系统。这听起来有点糊涂,但其实并不复杂(PHP4 内部结构图)。从功能上来分:我们可以分为三部分:

1、 解释器部分(Zend 以引擎),负责对输入代码的分析、翻译和执行;

2、 功能性部分(PHP功能函数以及扩展),负责具体实现语言的各种功能(比如它的函数等等);

3、 接口部分(SAPI),负责同 WEB 服务器的会话等功能。

Zend包括了第一部分的全部和第二部分的局部,PHP内核 包括了第二部分的局部和第三部分的全部。他们合起来称之为 PHP 包。Zend
构成了语言的核心,同时也包含了一些最基本的 PHP 预定义函数的实现。PHP 包(内核)则包含了所有创造出语言本身各种显著特性的模块。

(PHP 内部结构图)

从内容模块上来分:我们可以分为四层体系结构:

1)Zend引擎:Zend整体用纯c实现,是php的内核部分,它将php代码翻译(词法、语法解析等一系列编译过程)为可执行opcode的处理并实现相应的处理方法、实现了基本的数据结构(如hashtable、oo)、内存分配及管理、提供了相应的api方法供外部调用,是一切的核心,所有的外围功能均围绕zend实现。

2)Extensions扩展:围绕着zend引擎,extensions通过组件式的方式提供各种基础服务,我们常见的各种内置函数(如array系列)、标准库等都是通过extension来实现,用户也可以根据需要实现自己的extension以达到功能扩展、性能优化等目的(如贴吧正在使用的php中间层、富文本解析就是extension的典型应用)。

3)Sapi :Sapi全称是Server
Application Programming
Interface,也就是服务端应用编程接口,sapi通过一系列钩子函数,使得php可以和外围交互数据,这是php非常优雅和成功的一个设计,通过sapi成功的将php本身和上层应用解耦隔离,php可以不再考虑如何针对不同应用进行兼容,而应用本身也可以针对自己的特点实现不同的处理方式。

4)上层应用: 这就是我们平时编写的php程序,通过不同的sapi方式得到各种各样的应用模式,如通过webserver实现web应用、在命令行下以脚本方式运行等等。

                                                                              (php结构 )

架构思想:引擎(Zend)+扩展(ext)的模式:降低内部耦合

中间层(sapi):web server和php的通信接口, 隔绝web server和php。

如果php是一辆车,那么

车的框架就是php本身,即是我们外面看到一套完整系统。

Zend是车的引擎(发动机)

Ext下面的各种组件就是车的轮子

Sapi可以看做是公路,车可以跑在不同类型的公路上

而一次php程序的执行就是汽车跑在公路上。

因此,我们需要:性能优异的引擎+合适的车轮+正确的跑道

2、php生命周期

查看:深入理解php底层:php生命周期 :http://blog.csdn.net/hguisu/article/details/7377520

3 、sapi

如前所述,sapi通过通过一系列的接口,使得外部应用可以和php交换数据并可以根据不同应用特点实现特定的处理方法,我们常见的一些sapi有:

1) 、apache2handler 这是以作为,采用模式运行时候的处理方式,也是现在应用最广泛的一种。

2)、cgi :webserverphpfastcgifastcgi+phpwebserver3)、cli :

Sapi的定义及主要接口函数:

  1. struct _sapi_module_struct {
  2. char *name;         //  名字标识
  3. char *pretty_name;  // 更好理解的名字
  4. int (*startup)(struct _sapi_module_struct *sapi_module);    //  启动函数
  5. int (*shutdown)(struct _sapi_module_struct *sapi_module);   //  关闭方法
  6. int (*activate)(TSRMLS_D);  //激活
  7. int (*deactivate)(TSRMLS_D);    //  停用
  8. int (*ub_write)(const char *str, unsigned int str_length TSRMLS_DC);
  9. //  没有缓存的写操作(unbuffered write)
  10. void (*flush)(void *server_context);    //  flush
  11. struct stat *(*get_stat)(TSRMLS_D);     //  get uid
  12. char *(*getenv)(char *name, size_t name_len TSRMLS_DC); //  getenv
  13. void (*sapi_error)(int type, const char *error_msg, ...);   /* error
  14. handler */
  15. int (*header_handler)(sapi_header_struct *sapi_header, sapi_header_op_enum
  16. op,
  17. sapi_headers_struct *sapi_headers TSRMLS_DC);   /* header handler */
  18. /* send headers handler */
  19. int (*send_headers)(sapi_headers_struct *sapi_headers TSRMLS_DC);
  20. void (*send_header)(sapi_header_struct *sapi_header,
  21. void *server_context TSRMLS_DC);   /* send header handler */
  22. int (*read_post)(char *buffer, uint count_bytes TSRMLS_DC); /* read POST
  23. data */
  24. char *(*read_cookies)(TSRMLS_D);    /* read Cookies */
  25. /* register server variables */
  26. void (*register_server_variables)(zval *track_vars_array TSRMLS_DC);
  27. void (*log_message)(char *message);     /* Log message */
  28. time_t (*get_request_time)(TSRMLS_D);   /* Request Time */
  29. void (*terminate_process)(TSRMLS_D);    /* Child Terminate */
  30. char *php_ini_path_override;    //覆盖ini路径
  31. ...
  32. ...
  33. };

这里介绍一下其中一些主要函数

· startup:php被调用时初始化操作,比如cgi模式,在startup的时候会加载所有的extension并执行模块初始化工作。

· shutdown:php关闭时收尾工作

· activate:请求初始化

· dectivate:请求结束时收尾工作

· ub_write:指定数据输出方式,比如apache2handler方式,由于php作为apache的一个so存在,因此其输出也就是调
                         用apache的ap_write函数,而在cgi模式下,会系统调用write。

·  sapi_error:错误处理函数

·  read_post:读取post数据

·  register_server_variables:往$_SERVER中注册环境变量这个一般根据不同协议标准注册注册的变量。

在php源码中,sapi实现了很多接口:如下图:

4、php脚本的执行

SAPI处于PHP架构的上层,而真正的脚本执行是有Zend引擎来完成。

目前语言分为两类:

 第一类:编译型语言.如c/c++ Java之类,他们的共性是运行之前必须对源代码进行编译,然后运行编译后的目标文件。

 第二类语言:解释型语言:如PHP,Ruby,Python。他们需要解释器来执行这些源代码。实际上这些语言还是要经过编译环节的。只不过他们在运行的时候进行编译,为了效率,并不是每次执行的时候都会重新编译,比如PHP的各种opcode缓存扩展(如APC Xcache等)。

说明:PHP从2000年发布的PHP4开始就不是解释性语言。当一个PHP脚本被执行的时候,首先PHP源代码由Zend引擎编译成名为Zend opcodes的机器代码。这些代码保存在RAM中。然后执行opcodes运行真正的脚本。因此,PHP实际上和Java,C#等语言一样是编译语言。否则,它的执行会很慢。

我们来看PHP脚本是怎么被执行的。如hello.php:

  1. <?php
  2. $str = "Hello world!\n";
  3. echo $str;

命令行执行:php   hello.php

输出结果显然是:Hello world!

但是执行脚本的时候,PHP/Zend做了什么呢?

4.1、程序的执行:

1)传递给php程序需要的执行文件hello.php,php程序完成基本的准备工作后启动PHP及Zend引擎,加载注册的扩展模块。

2) 初始化完后读取脚本文件,Zend引擎对脚本进行此词法分析,语法分析,然后有Zend引擎编译成opcode码,最后执行              opcode码。

php代码的执行过程如下图:

php实现了一个典型的动态语言执行过程:拿到一段代码后,经过词法解析、语法解析等阶段后,源程序会被翻译成一个个指令(opcodes),然后ZEND虚拟机顺次执行这些指令完成操作。PHP本身是用c实现的,因此最终调用的也都是c的函数,实际上,我们可以把php看做是一个c开发的软件。

通过上面描述不难看出,php的执行的核心是翻译出来的一条一条指令,也即opcode.

4.2、词法分析和语法分析

解释器一般包括两部分:

1)、 读取源程序,并处理语言结构

2)、处于语言结构并生成目标程序

而Lex和Yacc可以解决第一个问题。很多编程都有Lex/Yacc作为语言的词法语法分析生成器,比如PHP,Python、Ruby已经MySQL的sql语言。

Lex生成词法分析器。

Yacc语法分析生成器

4. 3、opcode

PHP 构建在Zend虚拟机(Zend VM)之上的,PHP的opcode就是ZEND 虚拟机中的指令,即Opcode是php程序执行的最基本单位。

时间: 2024-08-15 08:22:18

探究PHP底层的相关文章

WinDbg探究CLR底层(1) - 应用程序域

一.什么是应用程序域 操作系统由于其稳定性与可靠性的要求,都会使用隔离层,来确保运行在某个隔离层内的代码不会对其他隔扇层的代码产生影响.如Windows通过进程来实现这种隔离机制,所能的可执行代码.数据.以及其它资源都被包含在进程中,系统其他进程通常不允许对它们进行访问.同理..NET应用程序同样也是被局限在进程内执行,但是.NET还进一步引入了另一种逻辑隔离层,也就是我们这里说的应用程序域(AppDomain). 二.如何查看应用程序域 下面用一个例子看看应用程序域: using System

小码哥iOS底层原理班怎么样

众所周知 小码哥的iOS是不错的,对于很多人来说自己从事iOS就是从小码哥开始的,随着发展现阶段的iOS并不如之前那么火热了,那么还有学习iOS的必要呢?回答是肯定的,一句老话:活到老学到老,人想要进步想要更好地生活,那么是离不开学习的.那么现在告诉大家个好消息,iOS底层原理班开班啦!MJ亲授,感兴趣的小伙伴们不要错过了!课程亮点1.市面**iOS高级开发课程,由MJ老师亲自研发,全程精心实力打造.2.为iOS开发者量身打造,深入研究iOS底层的方方面面.掌握了底层,你会发现其他的编程语言.操

30岁后的程序员都做什么去了

最近,很多人都在讨论"中年危机",中年危机,一般指39-65岁的中年人经历的一系列事业.家庭.感情.健康上的困境.现在的90后程序员们,他们之中大多数的年龄在四舍五入之后都满30岁了. 年龄的增长,往往也意味着身上的责任逐渐变多.他们也就逐渐承担起事业.家庭甚至社会上的责任,而是适应这些责任并不是一朝一夕的事儿.这时候的他们在看了很多关于程序员30多岁被辞退等新闻后,不仅发出感慨,程序员真的是个青春饭职业?那些30岁后的程序员都做什么去了? 我们先来看一张图,这是网传的程序员职业路线图

有了 Spring Boot,为什么还要懂 Spring MVC?

01 什么是 Spring Boot? 首先,Spring Boot 是现在比较流行的框架,可以实现快速开发,包括我自己也在用它开发项目. 其优点是简化了 Spring 相关组件的配置,实现自动配置,降低了项目搭建的复杂度,使开发变得更加简便,从而提升开发效率. Spring Boot 本身并不提供 Spring 框架的核心特性以及扩展功能,只是用于快速.敏捷地开发新一代基于 Spring 框架的应用程序. Spring Boot 并不是用来替代 Spring 的解决方案,而是和 Spring

从底层谈WebGIS 原理设计与实现(二):探究本质,WebGIS前端地图显示之地图比例尺换算原理

从底层谈WebGIS 原理设计与实现(二):探究本质,WebGIS前端地图显示之地图比例尺换算原理 作者:naaoveGI-    文章来源:http://www.cnblogs.com/naaoveGIS/    点击数:2453    更新时间:2014-9-12 摘要:前面我不厌其烦的给大家说了很多本节的题外话,现在言归正传,我们开始这个系列中的第一个问题,地图比例尺换算原理.想要从底层实现瓦片的显示,我们首先必须了解瓦片本身.我们用arcgis切完图后,打开发布的服务或者打开config

jsp:set/getProperty底层实现的探究

关于jsp:set/getProperty底层实现的探究 今天上课讲到<jsp:useBean>时涉及到了<jsp:setProperty>和<jsp:getProperty>两个标签.使用它俩可以获取和修改JavaBean中Java类的属性值,后面例子中又给出了直接调用Java类方法获取和修改属性值的方法,我们发现二者结果是一样的,旁边的hyx给出了关键性的问题,setP和getP实现机制和类方法调用一致吗?我心生疑问. 我们来一探究竟: 1. 起初我先注释掉*.Ja

探究JS V8引擎下的“数组”底层实现

本文首发于 vivo互联网技术 微信公众号? 链接:https://mp.weixin.qq.com/s/np9Yoo02pEv9n_LCusZn3Q 作者:李超 JavaScript 中的数组有很多特性:存放不同类型元素.数组长度可变等等,这与数据结构中定义的数组结构或者C++.Java等语言中的数组不太一样,那么JS数组的这些特性底层是如何实现的呢,我们打开V8引擎的源码,从中寻找到了答案.V8中对数组做了一层封装,使其有两种实现方式:快数组和慢数组,快数组底层是连续内存,通过索引直接定位,

深入探究递归神经网络:大牛级的训练和优化如何修成?

深入探究递归神经网络:大牛级的训练和优化如何修成? 摘要:不同于传统FNN,RNN无需在层面之间构建,同时引入定向循环,能够更好地处理高维度信息的整体逻辑顺序.本文中,MIT的Nikhil Buduma将带您深入探析RNN的原理.训练和优化等各方面的内容,以及RNN已经获取的一些成就. 在深度学习领域,传统的前馈神经网络(feed-forward neural net,简称FNN)具有出色的表现,取得了许多成功,它曾在许多不同的任务上——包括手写数字识别和目标分类上创造了记录.甚至到了今天,FN

Java知识探究一:关于IO类库

经过组织考察,令我忽然发觉自己在最常用的Java中也有很多不明白的地方,实为平身一大憾事,今天特意抽时间将这些点滴记录下来,与大家一起分享 第一批想整理的知识点如下: Java的IO探究,IO的整个结构与发展,顺带附上公司某小工写的断点续传代码学习. Java的异常机制,关于编译时异常和运行时异常的探究. JavaCommon包的理解,尤其是collection包的一些小看法,其实容器嘛,什么样的Utils也逃不出一些基本的范畴,比如存.取.排序.安全性.校验等等等. 闲话不多说,先开始今天的主