PHP代码的执行

简介:



先看下PHP的结构图:

1)Zend Engine

Zend引擎是PHP实现的核心,提供了语言实现上的基础设施。例如:PHP的语法实现,脚本的编译运行环境, 扩展机制以及内存管理等。

2)Extensions

围绕着zend引擎,Extensions通过组件式的方式提供各种基础服务,我们常见的各种内置函数(如MySQL系列)、标准库等都是通过Extension来实现,用户也可以根据需要实现自己的extension以达到功能扩展、性能优化等目的。

3)SAPI

SAPI(Server Application Programming Interface)指的是PHP具体应用的编程接口。就像PC一样,无论安装哪些操作系统,只要满足了PC的接口规范都可以在PC上正常运行。

4)架构思想

如果php是一辆车,那么车的框架就是php本身,Zend是车的引擎(发动机),Ext下面的各种组件就是车的轮子,SAPI可以看做是公路,车可以跑在不同类型的公路上,而一次php程序的执行就是汽车跑在公路上。因此,我们需要:性能优异的引擎+合适的车轮+正确的跑道。

 

一、Apache

Apache是Apache软件基金会的一个开放源代码的Web服务器,Apache支持许多特性,大部分通过模块扩展实现。

常见的模块包括mod_auth(权限验证)、mod_ssl(SSL和TLS支持) mod_rewrite(URL重写)等。

下图为Apache的逻辑构成以及与操作系统的关系:

 

1)Apache的mod_php5模块

当PHP需要在Apache服务器下运行时,可以用mod_php5模块的形式集成。

此时mod_php5模块的作用是接收Apache传递过来的PHP文件请求,并处理这些请求, 然后将处理后的结果返回给Apache。

 

2)Apache的运行过程

Apache的运行分为启动阶段和运行阶段。

在运行阶段,Apache主要工作是处理用户的服务请求。

Apache对HTTP的请求可以分为连接、处理和断开连接三个大的阶段。同时也可以分为11个小的阶段:

Post-Read-Request,URI Translation,Header Parsing,Access Control,Authentication,

Authorization,MIME Type Checking,FixUp,Response,Logging,CleanUp。

 

3)Apache Hook机制

模块可以在Apache的任何一个处理阶段中挂接(Hook)上自己的处理函数,从而参与Apache的请求处理过程。

 

二、FastCGI

1)CGI

  CGI全称是“通用网关接口”(Common Gateway Interface),描述了客户端和服务器程序之间传输数据的一种标准。它可以让一个客户端,从网页浏览器向执行在Web服务器上的程序请求数据。CGI用来沟通程序(如PHP, Python, Java)和Web服务器(Apache2, Nginx),理论上任何语言编写的程序都可以通过CGI来提供Web服务。

  比如现在请求的是“index.php”,根据配置文件,Apache知道这个不是静态文件,需要去找PHP解析器来处理,那么它会把这个请求简单处理后交给PHP解析器。Apache会传url、查询字符串、POST数据、HTTP header等,而CGI就是规定要传哪些数据、以什么样的格式传递给后方处理这个请求的协议。

  当web服务器收到“index.php”这个请求后,会启动对应的CGI程序,这里就是PHP的解析器。接下来PHP解析器会解析php.ini、载入全部扩展并初始化全部数据结构,然后处理请求,再以CGI规定的格式返回处理后的结果,退出进程,web服务器再把结果返回给浏览器。

 

2)FastCGI

  CGI程序存在性能问题,每次请求都会重复“PHP解析器会解析php.ini、载入全部扩展并初始化全部数据结构”这些步骤。

  FastCGI是CGI的一种改进方案。FastCGI像是一个常驻(long-live)型的CGI, 它可以一直执行,在请求到达时不会花费时间去fork一个进程来处理(这是CGI最为人诟病的fork-and-execute模式)。

FastCGI工作流程的通俗版本如下:

1. Fastcgi会先启一个master,解析配置文件,初始化执行环境,然后再启动多个worker。

2. 当请求过来时,master会传递给一个worker,然后立即可以接受下一个请求。这样就避免了重复的劳动,效率自然是高。

3. 当worker不够用时,master可以根据配置预先启动几个worker等着。

4. 当空闲worker太多时,也会停掉一些,这样就提高了性能,也节约了资源。

FastCGI工作流程的专业版本如下:

1. Web Server启动时载入FastCGI进程管理器(IIS ISAPI或Apache Module)

2. FastCGI进程管理器自身初始化,启动多个CGI解释器进程(可见多个php-cgi)并等待来自Web Server的连接。

3. 当客户端请求到达Web Server时,FastCGI进程管理器选择并连接到一个CGI解释器。Web server将CGI环境变量和标准输入发送到FastCGI子进程php-cgi。

4. FastCGI子进程完成处理后将标准输出和错误信息从同一连接返回Web Server。当FastCGI子进程关闭连接时, 请求便告处理完成。FastCGI子进程接着等待并处理来自FastCGI进程管理器(运行在Web Server中)的下一个连接。 在CGI模式中,php-cgi在此便退出了。


3)PHP-CGI

PHP-CGI是PHP自带的FastCGI管理器。

PHP-CGI的不足:

1. php-cgi变更php.ini配置后需重启php-cgi才能让新的php-ini生效,不可以平滑重启。

2. 直接杀死php-cgi进程,php就不能运行了。(PHP-FPM和Spawn-FCGI就没有这个问题,守护进程会平滑从新生成新的子进程。)

4)PHP-FPM

PHP-FPM是一个PHP FastCGI管理器,是只用于PHP的。

PHP-FPM其实是PHP源代码的一个补丁,旨在将FastCGI进程管理整合进PHP包中。必须将它patch到你的PHP源代码中,在编译安装PHP后才可以使用。

 

三、SAPI

下图为SAPI的简单示意图:

SAPI(Server abstraction API),它提供了一个接口,使得PHP可以和其他应用进行交互数据。

 

1)PHP执行的两个阶段,开始和结束

开始阶段:

a. 模块初始化阶段(MINIT), 在整个SAPI生命周期内(例如Apache启动以后的整个生命周期内或者命令行程序整个执行过程中), 该过程只进行一次

b. 模块激活阶段(RINIT),该过程发生在请求阶段, 例如通过url请求某个页面,则在每次请求之前都会进行模块激活(RINIT请求开始)

结束阶段:

a. 停用模块(RSHUTDOWN,对应RINIT)

b. 在SAPI生命周期结束(Web服务器退出或者命令行脚本执行完毕退出)时关闭模块(MSHUTDOWN,对应MINIT)

 

2)单进程SAPI生命周期

CLI/CGI模式的PHP属于单进程的SAPI模式。这类的请求在处理一次请求后就关闭。也就是只会经过如下几个环节:

开始 - 请求开始 - 请求关闭 - 结束。SAPI接口实现就完成了其生命周期。

a. 启动:初始化若干全局变量,初始化若干常量,初始化Zend引擎和核心组件,解析php.ini,全局操作函数的初始化,初始化静态构建的模块和共享模块(MINIT),禁用函数和类

b. 激活:激活Zend引擎,激活SAPI,环境初始化,模块请求初始化

c. 运行:要解析执行的文件,需要做词法分析、语法分析和中间代码生成操作,返回此文件的所有中间代码

d. 关闭:关闭请求的过程是一个若干个关闭操作的集合

e. 结束:flush,关闭Zend引擎

 

3)多进程SAPI生命周期

通常PHP是编译为apache的一个模块来处理PHP请求。

  Apache一般会采用多进程模式, Apache启动后会fork出多个子进程,每个进程的内存空间独立,每个子进程都会经过开始和结束环节, 不过每个进程的开始阶段只在进程fork出来以来后进行,在整个进程的生命周期内可能会处理多个请求。

 

4)多线程的SAPI生命周期

  多线程模式和多进程中的某个进程类似,不同的是在整个进程的生命周期内会并行的重复着 请求开始-请求关闭的环节

 

四、PHP脚本的执行

SAPI处于PHP整个架构较上层,而真正脚本的执行主要由Zend引擎来完成。

<?php
$str = "Hello, World!\n";
echo $str;

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

b. 初始化完成后读取脚本文件,Zend引擎对脚本文件进行词法分析,语法分析。

c. 编译成opcode执行。 如果安装了apc之类的opcode缓存, 编译环节可能会被跳过而直接从缓存中读取opcode执行。

很多编程语言都使用lex/yacc或他们的变体(flex/bison)来作为语言的词法语法分析生成器, 比如PHP、Ruby、Python以及MySQL的SQL语言实现。

PHP是构建在Zend虚拟机(Zend VM)之上的。PHP的opcode就是Zend虚拟机中的指令。

 

 

参考资料:

http://www.cnblogs.com/hongfei/archive/2012/06/12/2547119.html   PHP的执行原理/执行流程

http://www.php-internals.com/book/?p=chapt02/02-01-php-life-cycle-and-zend-engine   生命周期和Zend引擎

http://www.php-internals.com/book/?p=chapt02/02-02-01-apache-php-module  Apache模块

http://www.php-internals.com/book/?p=chapt02/02-02-03-fastcgi   FastCGI

http://segmentfault.com/q/1010000000256516    FastCgi与PHP-fpm之间是个什么样的关系

http://www.cnblogs.com/skynet/p/4173450.html  Nginx + CGI/FastCGI + C/Cpp

http://www.php-internals.com/book/?p=chapt02/02-02-00-overview   SAPI概述

http://rapheal.sinaapp.com/2013/11/14/php_zend_lex/  PHP-Zend引擎剖析之词法分析

http://rapheal.sinaapp.com/2013/11/20/php_zend_hello_world/  PHP-Zend引擎剖析之Hello World

http://www.nowamagic.net/librarys/veda/detail/1287    一次请求生命周期




    本文转自 咖啡机(K.F.J)   博客园博客,原文链接http://www.cnblogs.com/strick/p/5032943.html:,如需转载请自行联系原作者


相关文章
|
1月前
|
PHP 开发者
PHP中的命名空间:优雅解决代码冲突与组织结构
在PHP开发中,命名空间是一种重要的工具,可以帮助开发者避免代码冲突、提高代码组织结构和可读性。本文将深入探讨PHP中命名空间的概念、使用方法以及实际应用场景,帮助读者更好地理解和运用命名空间来优化他们的PHP代码。
拿php写个原生增删改查案例出来(提供全部代码+sql)
拿php写个原生增删改查案例出来(提供全部代码+sql)
拿php写个原生增删改查案例出来(提供全部代码+sql)
|
16天前
|
PHP 开发者
【专栏】介绍PHP的命名空间,它是一个用于封装代码、避免名称冲突的机制
【4月更文挑战第27天】本文介绍了PHP的命名空间,它是一个用于封装代码、避免名称冲突的机制。命名空间的作用包括:防止大型项目中的命名冲突,提升代码可读性和可维护性,以及方便代码重用。文章详细阐述了如何定义、导入命名空间,使用完全限定名称以及设置命名空间别名。通过实例展示了命名空间在项目模块划分和第三方库如Laravel中的应用,强调了命名空间在组织和管理PHP代码中的关键作用。
|
1月前
|
安全 PHP 开发工具
php代码加密 php-screw-plus
php代码加密 php-screw-plus
26 0
|
1月前
|
算法 PHP 数据安全/隐私保护
【实战】PHP代码逆向工具,轻松还原goto加密语句的神器!
`goto解密工具`是一款针对PHP的在线神器,能有效解密和还原goto加密代码,提升代码可读性和可维护性。支持单文件及50M压缩包一键解密,提供全效解决方案。通过实际案例展示了解密报错和理解复杂代码的能力,是PHP开发者解决goto难题的得力助手。立即体验:[在线PHP解密大师](https://copy.kaidala.com/dala/goto/index.html)。
27 1
|
1月前
|
算法 PHP 数据安全/隐私保护
【必备工具】解密PHP超强在线工具,一键goto代码解密
goto解密工具,php开发者的福音,能有效解密复杂的goto加密代码,提升代码可读性和可维护性。支持单文件及项目目录一键解密,最大处理50M压缩文件。通过具体案例展示其在解决报错和理解复杂开源项目中的强大功能。立即体验:https://copy.kaidala.com/dala/goto/index.html
45 0
|
2月前
|
PHP 开发者 UED
PHP 中的异常处理:提高代码健壮性的关键
【2月更文挑战第28天】在 PHP 开发中,异常处理是确保应用程序稳定性和可靠性的重要环节。本文将深入探讨 PHP 异常的概念、类型及其处理机制,并通过实例演示如何有效地捕获和处理异常,以增强代码的健壮性和用户体验。
php案例:判断这个文件是什么编程语言代码的文件(判断java或者php)
php案例:判断这个文件是什么编程语言代码的文件(判断java或者php)
php案例:判断这个文件是什么编程语言代码的文件(判断java或者php)