Loading... <h1 style="margin: 0px;padding: 0px;font-size: 12px">1、PHP是什么?</h1> <blockquote><p style="text-align:left">PHP 指的是我们从外面看到的一套完整的系统。这听起来有点糊涂,但其实并不复杂(PHP4 内部结构图)。从功能上来分:我们可以分为三部分:</p> <p>1、 解释器部分(Zend 以引擎),负责对输入代码的分析、翻译和执行;<br />2、 功能性部分(PHP功能函数以及扩展),负责具体实现语言的各种功能(比如它的函数等等);<br />3、 接口部分(SAPI),负责同 WEB 服务器的会话等功能。 <p>Zend包括了第一部分的全部和第二部分的局部,PHP内核 包括了第二部分的局部和第三部分的全部。他们合起来称之为 PHP 包。Zend 构成了语言的核心,同时也包含了一些最基本的 PHP 预定义函数的实现。PHP 包(内核)则包含了所有创造出语言本身各种显著特性的模块。</p> </blockquote> <p></p> <p> <img src="//cto.wang/usr/uploads/2016/07/20160703145028-60.png" title="1428659374134969.png" alt="1.png" /></p> <p> </p> <p> (PHP 内部结构图)</p> <p> 从内容模块上来分:我们可以分为四层体系结构:</p> <p></p> <blockquote><p>1)Zend引擎:Zend整体用纯c实现,是php的内核部分,它将php代码翻译(词法、语法解析等一系列编译过程)为可执行opcode的处理并实现相应的处理方法、实现了基本的数据结构(如hashtable、oo)、内存分配及管理、提供了相应的api方法供外部调用,是一切的核心,所有的外围功能均围绕zend实现。</p> <p>2)Extensions扩展:围绕着zend引擎,extensions通过组件式的方式提供各种基础服务,我们常见的各种内置函数(如array系列)、标准库等都是通过extension来实现,用户也可以根据需要实现自己的extension以达到功能扩展、性能优化等目的(如贴吧正在使用的php中间层、富文本解析就是extension的典型应用)。</p> <p>3)Sapi :Sapi全称是Server Application Programming Interface,也就是服务端应用编程接口,sapi通过一系列钩子函数,使得php可以和外围交互数据,这是php非常优雅和成功的一个设计,通过sapi成功的将php本身和上层应用解耦隔离,php可以不再考虑如何针对不同应用进行兼容,而应用本身也可以针对自己的特点实现不同的处理方式。</p> <p>4)上层应用: 这就是我们平时编写的php程序,通过不同的sapi方式得到各种各样的应用模式,如通过webserver实现web应用、在命令行下以脚本方式运行等等。</p> </blockquote> <p> <img src="//cto.wang/usr/uploads/2016/07/20160703145028-21.jpg" title="1428659390527213.jpg" alt="2.jpg" /></p> <p><span style="line-height: 32px"><span><strong> (php结构 )</strong></span></span></p> <blockquote><p><span style="line-height: 25px">其架构思想:引擎(Zend)+扩展(ext)的模式:降低内部耦合</span></p> <p> 中间层(sapi):web server和php的通信接口, 隔绝web server和php。</p> <p><span>如果php是一辆车,那么</span></p> <p><span>车的框架就是php本身,即是我们外面看到一套完整系统。</span></p> <p><span>Zend是车的引擎(发动机)</span></p> <p><span>Ext下面的各种组件就是车的轮子</span></p> <p><span>Sapi可以看做是公路,车可以跑在不同类型的公路上</span></p> <p><span>而一次php程序的执行就是汽车跑在公路上。</span></p> <p><span>因此,我们需要:性能优异的引擎+合适的车轮+正确的跑道</span></p> </blockquote> <h1 style="margin: 0px;padding: 0px"><span style="line-height: 32px">2、php生命周期</span></h1> <p><span style="line-height: 32px"><span> </span> 查看:深入理解php底层:php生命周期<span> </span><span>:http://blog.csdn.net/hguisu/article/details/7377520</span></span></p> <h1 style="margin: 0px;padding: 0px">3 、sapi</h1> <blockquote><p><span> 如前所述,</span><span>sapi</span><span>通过通过一系列的接口,使得外部应用可以和</span><span>php</span><span>交换数据并可以根据不同应用特点实现特定的处理方法,我们常见的一些</span><span>sapi</span><span>有:</span></p> <p><span><strong>1) 、apache2handler </strong></span>:<span>这是以</span><span>apache</span><span>作为</span><span>webserver</span><span>,采用</span><span>mod_php</span><span>模式运行时候的处理方式,也是现在应用最广泛的一种。</span></p> <p><span><strong>2)、cgi :</strong></span><span>这是</span><span>webserver</span><span>和</span><span>php</span><span>直接的另一种交互方式,也就是大名鼎鼎的</span><span>fastcgi</span><span>协议,在最近今年</span><span>fastcgi+php</span><span>得到越来越多的应用,也是异步</span><span>webserver</span><span>所唯一支持的方式。</span></p> <p><span><strong>3)、cli :</strong></span><span>命令行调用的应用模式</span></p> <p><span>如图:Sapi的简单示意图:</span></p> <p><span> <img src="//cto.wang/usr/uploads/2016/07/20160703145028-26.jpg" title="1428659400878420.jpg" alt="3.jpg" /></span></p> </blockquote> <p><span> Sapi的定义及主要接口函数:</span></p> <p><span></span></p> <pre class="brush:python;toolbar:false">struct _sapi_module_struct { char *name; // 名字标识 char *pretty_name; // 更好理解的名字 int (*startup)(struct _sapi_module_struct *sapi_module); // 启动函数 int (*shutdown)(struct _sapi_module_struct *sapi_module); // 关闭方法 int (*activate)(TSRMLS_D); //激活 int (*deactivate)(TSRMLS_D); // 停用 int (*ub_write)(const char *str, unsigned int str_length TSRMLS_DC); // 没有缓存的写操作(unbuffered write) void (*flush)(void *server_context); // flush struct stat *(*get_stat)(TSRMLS_D); // get uid char *(*getenv)(char *name, size_t name_len TSRMLS_DC); // getenv void (*sapi_error)(int type, const char *error_msg, ...); /* error handler */ int (*header_handler)(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC); /* header handler */ /* send headers handler */ int (*send_headers)(sapi_headers_struct *sapi_headers TSRMLS_DC); void (*send_header)(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC); /* send header handler */ int (*read_post)(char *buffer, uint count_bytes TSRMLS_DC); /* read POST data */ char *(*read_cookies)(TSRMLS_D); /* read Cookies */ /* register server variables */ void (*register_server_variables)(zval *track_vars_array TSRMLS_DC); void (*log_message)(char *message); /* Log message */ time_t (*get_request_time)(TSRMLS_D); /* Request Time */ void (*terminate_process)(TSRMLS_D); /* Child Terminate */ char *php_ini_path_override; //覆盖ini路径 ... ... };</pre> <p style="text-align:left"><span>这里介绍一下其中一些主要函数</span></p> <p style="text-align:left"><span>· </span><span>startup</span><span>:</span><span>php</span><span>被调用时初始化操作,</span><span>比如</span><span>cgi</span><span>模式,在</span><span>startup</span><span>的时候会加载所有的</span><span>extension</span><span>并执行模块初始化工作。</span></p> <p style="text-align:left"><span>· </span><span>shutdown</span><span>:</span><span>php</span><span>关闭时收尾工作</span></p> <p style="text-align:left"><span>· </span><span>activate</span><span>:请求初始化</span></p> <p style="text-align:left"><span>· </span><span>dectivate</span><span>:请求结束时收尾工作</span></p> <p style="text-align:left"><span>· </span><span>ub_write</span><span>:指定数据输出方式,</span><span>比如</span><span>apache2handler</span><span>方式,由于</span><span>php</span><span>作为</span><span>apache</span><span>的一个</span><span>so</span><span>存在,因此其输出也就是调 用</span><span>apache</span><span>的</span><span>ap_write</span><span>函数,而在</span><span>cgi</span><span>模式下,会系统调用</span><span>write</span><span>。</span></p> <p style="text-align:left"><span>· </span><span>sapi_error</span><span>:错误处理函数</span></p> <p style="text-align:left"><span>· </span><span>read_post</span><span>:读取</span><span>post</span><span>数据</span></p> <p style="text-align:left"><span>· </span><span>register_server_variables</span><span>:往</span><span>$_SERVER</span><span>中注册环境变量</span><span>这个一般根据不同协议标准注册注册的变量。</span></p> <p></p> <p>在php源码中,sapi实现了很多接口:如下图:</p> <p><img src="//cto.wang/usr/uploads/2016/07/20160703145028-21-1.jpg" title="1428659455138704.jpg" alt="4.jpg" /></p> <h1>4、php脚本的执行</h1> <blockquote><p> SAPI处于PHP架构的上层,而真正的脚本执行是有Zend引擎来完成。</p> <p>目前语言分为两类:</p> <p><strong> 第一类:编译型语言</strong>.如c/c++ java之类,他们的共性是运行之前必须对源代码进行编译,然后运行编译后的目标文件。</p> <p><strong> 第二类语言:解释型语言</strong>:如PHP,Ruby,Python。他们需要解释器来执行这些源代码。实际上这些语言还是要经过编译环节的。只不过他们在运行的时候进行编译,为了效率,并不是每次执行的时候都会重新编译,比如PHP的各种opcode缓存扩展(如APC Xcache等)。</p> <p><span style="background-color: yellow">说明:PHP</span><span>从2000</span><span>年发布的PHP4开始就不是解释性语言。当一个PHP脚本被执行的时候,首先PHP源代码由Zend引擎编译成名为Zend opcodes的机器代码。这些代码保存在RAM中。然后执行opcodes运行真正的脚本。因此,PHP实际上和Java,C#等语言一样是编译语言。否则,它的执行会很慢。</span></p> <p>我们来看PHP脚本是怎么被执行的。如hello.php:</p> <pre class="brush:python;toolbar:false"><?php $str = "Hello world!\n"; echo $str;</pre> </blockquote> <blockquote><p>命令行执行:php hello.php</p> <p>输出结果显然是:Hello world!</p> <p> 但是执行脚本的时候,PHP/Zend做了什么呢?</p> </blockquote> <h3>4.1、程序的执行:</h3> <blockquote><p>1)传递给php程序需要的执行文件hello.php,php程序完成基本的准备工作后启动PHP及Zend引擎,加载注册的扩展模块。</p> <p> 2) 初始化完后读取脚本文件,Zend引擎对脚本进行此词法分析,语法分析,然后有Zend引擎编译成opcode码,最后执行 opcode码。</p> </blockquote> <p><span> php</span><span>代码的执行过程如下图:</span></p> <p><span> <img src="//cto.wang/usr/uploads/2016/07/20160703145028-70.jpg" title="1428659525304677.jpg" alt="5.jpg" /></span></p> <p><span><br /></span></p> <blockquote><p><span> php实现了一个典型的动态语言执行过程:拿到一段代码后,经过词法解析、语法解析等阶段后,源程序会被翻译成一个个指令(opcodes),然后ZEND虚拟机顺次执行这些指令完成操作。PHP本身是用c实现的,因此最终调用的也都是c的函数,实际上,我们可以把php看做是一个c开发的软件。</span></p> <p><span> 通过上面描述不难看出,php的执行的核心是翻译出来的一条一条指令,也即opcode.</span></p> </blockquote> <h3><span>4.2、词法分析和语法分析</span></h3> <blockquote><p><span>解释器一般包括两部分:</span></p> <p><span>1)、 读取源程序,并处理语言结构</span></p> <p><span>2)、处于语言结构并生成目标程序</span></p> <p><span>而Lex和Yacc可以解决第一个问题。很多编程都有Lex/Yacc作为语言的词法语法分析生成器,比如PHP,Python、Ruby已经MySql的sql语言。</span></p> <p><span>Lex生成词法分析器。</span></p> <p><span>Yacc语法分析生成器</span></p> </blockquote> <h3><span>4. 3、opcode</span></h3> <blockquote><p><span>PHP 构建在Zend虚拟机(Zend VM)之上的,PHP的opcode就是ZEND 虚拟机中的指令,即Opcode是php程序执行的最基本单位。</span></p> </blockquote> 最后修改:2021 年 12 月 10 日 10 : 53 AM © 允许规范转载 赞赏 如果觉得我的文章对你有用,请随意赞赏 赞赏作者 支付宝微信