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 */
};
```
其中,php_ap2_register_hook是一系列的hook调用:
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...
原文地址:
mod_php模式原理探析的更多相关文章
- NSOperation, NSOperationQueue 原理探析
通过GNUstep的Foundation来尝试探索下NSOperation,NSOperationQueue 示例程序 写一个简单的程序 - (void)viewDidLoad { [super vi ...
- WebRTC的RTCPeerConnection()原理探析
从getUserMedia()到RTCPeerConnection(),自认为难度陡增.我想一方面是之前在Linux平台上学习ROS调用摄像头时,对底层的外设接口调用.摄像头参数都有学习理解:另一方面 ...
- 中文分词工具探析(二):Jieba
1. 前言 Jieba是由fxsjy大神开源的一款中文分词工具,一款属于工业界的分词工具--模型易用简单.代码清晰可读,推荐有志学习NLP或Python的读一下源码.与采用分词模型Bigram + H ...
- 深入探析koa之中间件流程控制篇
koa被认为是第二代web后端开发框架,相比于前代express而言,其最大的特色无疑就是解决了回调金字塔的问题,让异步的写法更加的简洁.在使用koa的过程中,其实一直比较好奇koa内部的实现机理.最 ...
- 开源中文分词工具探析(三):Ansj
Ansj是由孙健(ansjsun)开源的一个中文分词器,为ICTLAS的Java版本,也采用了Bigram + HMM分词模型(可参考我之前写的文章):在Bigram分词的基础上,识别未登录词,以提高 ...
- 开源中文分词工具探析(四):THULAC
THULAC是一款相当不错的中文分词工具,准确率高.分词速度蛮快的:并且在工程上做了很多优化,比如:用DAT存储训练特征(压缩训练模型),加入了标点符号的特征(提高分词准确率)等. 1. 前言 THU ...
- 开源中文分词工具探析(五):FNLP
FNLP是由Fudan NLP实验室的邱锡鹏老师开源的一套Java写就的中文NLP工具包,提供诸如分词.词性标注.文本分类.依存句法分析等功能. [开源中文分词工具探析]系列: 中文分词工具探析(一) ...
- [转载] Thrift原理简析(JAVA)
转载自http://shift-alt-ctrl.iteye.com/blog/1987416 Apache Thrift是一个跨语言的服务框架,本质上为RPC,同时具有序列化.发序列化机制:当我们开 ...
- Erlang调度器细节探析
Erlang调度器细节探析 Erlang的很多基础特性使得它成为一个软实时的平台.其中包括垃圾回收机制,详细内容可以参见我的上一篇文章Erlang Garbage Collection Details ...
随机推荐
- Re:从 0 开始的微服务架构--(三)微服务架构 API 的开发与治理--转
原文来自:聊聊架构公众号 前面的文章中有说到微服务的通信方式,Martin Folwer 先生在他对微服务的定义中也提到“每个服务运行在其独立的进程中,服务与服务间采用 轻量级的通信机制 互相协作(通 ...
- Java7里try-with-resources分析--转
原文地址:http://blog.csdn.net/hengyunabc/article/details/18459463 这个所谓的try-with-resources,是个语法糖.实际上就是自动调 ...
- mybatis的sql中使用$会出现sql注入示例
mybatis的sql中使用$会出现sql注入示例: 模拟简单登录场景: 页面代码: function login(){ //sql注入 var user = { username : "' ...
- (转载)Android支付宝支付封装代码
Android支付宝支付封装代码 投稿:lijiao 字体:[增加 减小] 类型:转载 时间:2015-12-22我要评论 这篇文章主要介绍了Android支付宝支付封装代码,Android支付的时候 ...
- UVa 10943 How do you add?【递推】
题意:给出n,k,问恰好有k个不超过n的数的和为n的方案数有多少 可以隔板法来做 现在有n个小球放到k个盒子里面,盒子可以为空 那么就是n-k+1个缝隙,放上k-1个隔板(k-1个隔板就分成了k份) ...
- FCC高级编程篇之Record Collection
Record Collection You are given a JSON object representing a part of your musical album collection. ...
- 【Henu ACM Round#24 D】Iterated Linear Function
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 把B提取出来就是一个等比数列了. 求和一下会发现是这种形式. \(B*\frac{(A^n-1)}{A-1}+A^n*x\) 则求一 ...
- Maven学习总结(22)——Maven常用插件介绍
我们都知道Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成,例如编译源代码是由maven- compiler-plugin完成的.进一步说,每个任务对应 ...
- [MySQL]快速解决"is marked as crashed and should be repaired"故障[转]
Table '.\Tablename\posts' is marked as crashed and should be repaired 提示说论坛的帖子表posts被标记有问题,需要修复.我记得以 ...
- UVA 11020 Efficient Solutions+multiset的应用
题目链接:点击进入 首先来讲,非常easy看到我们事实上仅仅要维护优势人群的集合:假设增加一个新的人,我们首先看一下优势人群中是否有人会让这个人失去优势,假设没有,则将这个人插入集合中.但要注意到这个 ...