mod_php模式原理探析

1、PHP与Apache工作模式

在传统的LAMP架构中,PHP与Apache交互时,至少有两种方式『运行PHP』:

  • 使用CGI:Apache发送请求至php-cgi进程,php-cgi进程调用PHP解释器,然后由PHP解释器进程解释php脚本代码。
  • 使用mod_php作为Apache的一个模块:PHP解释器作为Apache的一个内置模块,即不存在外部的PHP进程,而是由Apache(中的mod_php模块)进程解释执行PHP脚本 - 这意味着PHP与Apache通信更方便快捷。

其中,『运行PHP』是指调用PHP解释器解释执行PHP脚本。

通过php的‘php_sapi_name()’函数可知道,当前系统采用哪种工作模式。如当值为’apache2handler’时即表示:mod_php模式。

2、Apache模块加载原理

Apache的模块可以以静态方式编译到可执行程序中,也可以在Apache运行过程中动态加载(以动态链接库的方式)。这意味着:可以对Apache服务器程序进行扩展而无需重新源码编译它,甚至无需重启它。
所需要做的就是:向服务器发送HUP或者AP_SIG_GRACEFUL信号,通知服务器重新加载模块。
关于向Apache发送HUP信号:

‘Sending the HUP or restart signal to the parent causes it to kill off its children like in TERM, but the parent doesn‘t exit. It re-reads its configuration files, and re-opens any log files. Then it spawns a new set of children and continues serving hits.

回到mod_php模块,Apache动态加载模块的过程:

  • 首先,在Apache配置文件http.conf中增加:LoadModule php7_module libexec/apache2/libphp7.so,表示运行过程中加载PHP模块的动态链接库文件:libphp7.so。
  • 然后,通过Apache的内部函数(以Hook的方式)获取动态链接库的内容,并将PHP模块的内容加载到内存中指定的变量中。

其中PHP7源码中,PHP模块(php7_module)的数据结构为:


AP_MODULE_DECLARE_DATA module php7_module = {
STANDARD20_MODULE_STUFF, /宏,包括了module结构的前8个字段:版本号、小版本号、模块索引、模块名、当前模块指针、下一个动态加载的模块指针、魔数、rewrite_args函数指针/
create_php_config, /* create per-directory config structure /
merge_php_config, / merge per-directory config structures /
NULL, / create per-server config structure /
NULL, / merge per-server config structures /
php_dir_cmds, / command apr_table_t /
php_ap2_register_hook / register hooks */
};

<p>其中,php_ap2_register_hook是一系列的hook调用:</p>
<pre><code class="C">void php_ap2_register_hook(apr_pool_t *p)
{
     ap_hook_pre_config(php_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
     ap_hook_post_config(php_apache_server_startup, NULL, NULL, APR_HOOK_MIDDLE);
     ap_hook_handler(php_handler, NULL, NULL, APR_HOOK_MIDDLE);
#ifdef ZEND_SIGNALS
     ap_hook_child_init(zend_signal_init, NULL, NULL, APR_HOOK_MIDDLE);
#endif
     ap_hook_child_init(php_apache_child_init, NULL, NULL, APR_HOOK_MIDDLE);
}
  • pre_config、post_config、child_init是启动时执行的钩子,它们会在Apache服务器启动时调用。其中,在post_config钩子中启动PHP解释器模块(由php_apache_server_startup函数实现:‘通过调用sapi_startup启动sapi, 并通过调用php_apache2_startup来注册sapi module struct(此结构在本节开头中有说明), 最后调用php_module_startup来初始化PHP, 其中又会初始化ZEND引擎,以及填充zend_module_struct中 的treat_data成员(通过php_startup_sapi_content_types)等‘)。
  • handler是请求时执行的钩子,它会在Apache服务器处理请求时调用。

3、Apache Hooking机制:

在Apache2.4中如果需要处理请求时,你只需要创建一个钩子(Hook),挂于请求处理程序上。
一个钩子,本质上是一条信息:告诉服务器它要么服务用户发起的请求要么只是瞥一眼该请求。Apache所有的模块(包括mod_rewrite, mod_authn_*, mod_proxy等)均是将钩子挂于请求程序的各个部分来实现的 - are hooked into specific parts of the request process。

modules serve different purposes; Some are authentication/authorization handlers, others are file or script handlers while some third modules rewrite URIs or proxies content.

Apache服务器本身无需知道每个模块具体负责处理哪个部分以及处理什么,它只需要:在客户端请求达到的时候询问下哪个模块对这个请求『感兴趣』即可,而每个模块只需选择要还是不要,如果要那按照钩子定义的内容处理然后返回接口。

图片来源于Apache官网

Apache允许外部模块可以将自定义的函数注入到自己的请求处理循环中,从而参与Apache的请求处理过程。
通过Hook机制,PHP模块可以在Apache请求处理流程中负责处理那些关于php脚本的请求(即负责解释、执行php脚本)。
具体实现方式可以详见在PHP源码中实现Apahce的ap_hook_post_config钩子:PHP以模块方式注册到Apache的挂钩上去。这样在Apache进程运行时一有php请求,就可以加载动态链接库(libphp7.so文件)形式的PHP模块,用来处理php请求。

REFERENCES

1、http://stackoverflow.com/ques...
2、http://www.phppan.com/2011/01...
3、https://github.com/php/php-sr...
4、https://github.com/php/php-sr...
5、https://httpd.apache.org/docs...

原文地址:

原文地址:https://www.cnblogs.com/lalalagq/p/9962057.html

时间: 2024-07-31 21:03:30

mod_php模式原理探析的相关文章

读后感(一) web运作原理探析

tomcat与java web开发技术详解之web运作原理探析 成为一名web开发工程师,首先要明白web运作原理,原理可以带我们更好的去解决底层问题,怎么去理解现在流行的开源框架,甚至如何去自己写一个框架. 1 什么是web? web是网络上使用最广泛的分布式框架.它采用了客户端/服务器的通信模式,客户端可以是浏览器,通过浏览器它就可以连接服务器,访问许多服务器浏览各种各样的网站,这也是为什么说web是一种分布式的运用框架了. 2 URL 我们访问一个网站的时候会在浏览器显示一个网站地址,比如

Web运作原理探析

Web运作原理探析 1.1 web的 概念 Web是一种分布式的应用架构,旨在共享分布在网络上的各个Web服务器中的所有互相链接的信息. 1.2 HTML是指超文本标记语言. 1.3 URL简介 URL是Uniform Resource Locator的缩写,表示统一资源定位符,它是专门为了标识网络上的资源位置而设计的一种编址方式. 1.4 HTTP协议简介 HTTP 协议(Hypertext Transfer Portocol,超级文本传输协议). 当用户在浏览器中输入URL地址"http:/

[转载] Thrift原理简析(JAVA)

转载自http://shift-alt-ctrl.iteye.com/blog/1987416 Apache Thrift是一个跨语言的服务框架,本质上为RPC,同时具有序列化.发序列化机制:当我们开发的service需要开放出去的时候,就会遇到跨语言调用的问题,JAVA语言开发了一个UserService用来提供获取用户信息的服务,如果服务消费端有PHP/Python/C++等,我们不可能为所有的语言都适配出相应的调用方式,有时候我们会很无奈的使用Http来作为访问协议;但是如果服务消费端不能

【转】代码签名探析

转至:objc中国 代码签名探析 dopcn  15 Oct 2014 分享文章 "用户会感激代码签名带来的好处" – Apple Developer Library: Code Signing Guide 在 iOS 或 OS X 平台上进行应用开发时,你所需要使用的 API 大多设计得简洁明了.你可以轻易地实现酷炫的动画效果,便捷地进行应用发布前测试,或是用 Core Data 将数据安全的存储在本地.但是总有一天,你会碰上代码签名 (code signing) 和配置文件 (pr

浏览器环境下JavaScript脚本加载与执行探析之动态脚本与Ajax脚本注入

在<浏览器环境下JavaScript脚本加载与执行探析之defer与async特性>中,我们研究了延迟脚本(defer)和异步脚本(async)的执行时机.浏览器支持情况.浏览器bug以及其他的细节问题.而除了defer和async特性,动态脚本和Ajax脚本注入也是两种常用的创建无阻塞脚本的方法.总的来看,这两种方法都能达到脚本加载不影响页面解析和渲染的作用,但是在不同的浏览器中,这两种技术所创建的脚本的执行时机还是有一定差异,今天我们再来探讨一下通过动态脚本技术和Ajax注入的脚本在这些方

深入探析 Rational AppScan Standard Edition 多步骤操作

序言 IBM Rational AppScan Standard(下文简称 AppScan)作为面向 Web 应用安全黑盒检测的自动化工具,得到业界的广泛认可和应用.很多人使用 AppScan 时都采用其强大的手工探索加自动探测的方式,然而这种方式并不适用于所有场景.使用 AppScan 进行安全扫描时,我们必须保证 AppScan 探索出来的 URL 的有效性(尤其是用户想导出这些探索结果以供复用的情况下),有效性即指该 URL 对应的 HTTP 请求能被服务器端接受并按照期望的方式进行处理.

Java Annotation 及几个常用开源项目注解原理简析

PDF 版: Java Annotation.pdf, PPT 版:Java Annotation.pptx, Keynote 版:Java Annotation.key 一.Annotation 示例 Override Annotation Java 1 2 3 @Override public void onCreate(Bundle savedInstanceState); Retrofit Annotation Java 1 2 3 @GET("/users/{username}&quo

lvs-dr模式原理详解和可能存在的“假负载均衡”

原文地址: http://blog.csdn.net/lengzijian/article/details/8089661 lvs-dr模式原理 转载注明出处:http://blog.csdn.net/lengzijian/article/details/8089661 先附上一张原理图: 为了更清晰的表述lvs-dr原理,我们用tcpdump工具打印出tcp数据,查看mac地址的更改情况,绘制出如下的时序图: 图1表示201收到转发消息,图2表示200收到转发请求(下面两张为错误的图,错误的理

合并财务报表分步合并与一次合并的差异探析

多层控股关系下,集团编制合并报表的顺序采用一次合并法还是分步合并法,两者的结果是否相同,其使用有否受到限制,实务中存在疑惑.本文着重分析在抵销内部交易未实现损益.同一控制下企业合并.购买子公司少数股权等事项中,不同合并顺序的应用及其对于合并报表权益结构的影响,探讨在实务中如何消除因合并顺序不同而引发的差异,以提高合并报表的编制质量. 一.多层控股关系下有关合并报表顺序的两种方法 当存在多层控股关系时,编制合并报表的合并顺序一般有分步合并和一次合并两种方法. (一)分步合并法 分步合并法,指企业存