探究PHP底层

探究PHP底层

一、PHP是什么?

 

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

一、 解释器部分(Zend 以引擎),负责对输入代码的分析、翻译和执行;
二、 功能性部分(PHP功能函数以及扩展),负责具体实现语言的各类功能(好比它的函数等等);
三、 接口部分(SAPI),负责同 WEB 服务器的会话等功能。
Zend包括了第一部分的所有和第二部分的局部,PHP内核 包括了第二部分的局部和第三部分的所有。他们合起来称之为 PHP 包。Zend 构成了语言的核心,同时也包含了一些最基本的 PHP 预约义函数的实现。PHP 包(内核)则包含了全部创造出语言自己各类显著特性的模块。

                  

                                       

                                                                                                     (PHP 内部结构图)java

        从内容模块上来分:咱们能够分为四层体系结构:python

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

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

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

4)上层应用: 这就是咱们平时编写的php程序,经过不一样的sapi方式获得各类各样的应用模式,如经过webserver实现web应用、在命令行下以脚本方式运行等等。算法

          

                                                                              (php结构 )sql

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

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

若是php是一辆车,那么

车的框架就是php自己,便是咱们外面看到一套完整系统。

Zend是车的引擎(发动机)

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

Sapi能够看作是公路,车能够跑在不一样类型的公路上

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

所以,咱们须要:性能优异的引擎+合适的车轮+正确的跑道

 

      如前所述,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.    
  7.     int (*activate)(TSRMLS_D);  //激活  
  8.     int (*deactivate)(TSRMLS_D);    //  停用  
  9.    
  10.     int (*ub_write)(const char *str, unsigned int str_length TSRMLS_DC);  
  11.      //  没有缓存的写操做(unbuffered write)  
  12.     void (*flush)(void *server_context);    //  flush  
  13.     struct stat *(*get_stat)(TSRMLS_D);     //  get uid  
  14.     char *(*getenv)(char *name, size_t name_len TSRMLS_DC); //  getenv  
  15.    
  16.     void (*sapi_error)(int type, const char *error_msg, ...);   /* error  
  17. handler */  
  18.    
  19.     int (*header_handler)(sapi_header_struct *sapi_header, sapi_header_op_enum   
  20. op,  
  21.         sapi_headers_struct *sapi_headers TSRMLS_DC);   /* header handler */  
  22.    
  23.      /* send headers handler */  
  24.     int (*send_headers)(sapi_headers_struct *sapi_headers TSRMLS_DC);  
  25.    
  26.     void (*send_header)(sapi_header_struct *sapi_header,  
  27.             void *server_context TSRMLS_DC);   /* send header handler */  
  28.    
  29.     int (*read_post)(char *buffer, uint count_bytes TSRMLS_DC); /* read POST  
  30. data */  
  31.     char *(*read_cookies)(TSRMLS_D);    /* read Cookies */  
  32.    
  33.     /* register server variables */  
  34.     void (*register_server_variables)(zval *track_vars_array TSRMLS_DC);  
  35.    
  36.     void (*log_message)(char *message);     /* Log message */  
  37.     time_t (*get_request_time)(TSRMLS_D);   /* Request Time */  
  38.     void (*terminate_process)(TSRMLS_D);    /* Child Terminate */  
  39.    
  40.     char *php_ini_path_override;    //覆盖ini路径  
  41.    
  42.     ...  
  43.     ...  
  44. };  

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

· startupphp被调用时初始化操做,好比cgi模式,在startup的时候会加载全部的extension并执行模块初始化工做。

· shutdownphp关闭时收尾工做

· activate:请求初始化

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

· ub_write:指定数据输出方式,好比apache2handler方式,因为php做为apache的一个so存在,所以其输出也就是调                          用apacheap_write函数,而在cgi模式下,会系统调用write

·  sapi_error:错误处理函数

·  read_post:读取post数据

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


在php源码中,sapi实现了不少接口:以下图:




四、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)传递给php程序须要的执行文件hello.php,php程序完成基本的准备工做后启动PHP及Zend引擎,加载注册的扩展模块。

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


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

                           


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

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

4.二、词法分析和语法分析

解释器通常包括两部分:

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

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


而Lex和Yacc能够解决第一个问题。不少编程都有Lex/Yacc做为语言的词法语法分析生成器,好比PHP,Python、Ruby已经MySQL的sql语言。

Lex生成词法分析器。

Yacc语法分析生成器

4. 三、opcode

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

相关文章
相关标签/搜索