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 ...
随机推荐
- Linux基础03
** Linux基本操作常用命令(三) ** Linux的软件包 Linux的软件把分为“源码包”和“二进制包” 源码包:免费,开源 二进制包:系统默认包,即RPM包(上一节我们通过rpm卸载过ope ...
- ES6 | class类的基本语法总结
类和模块的内部,默认就是严格模式,所以不需要使用use strict指定运行模式.只要你的代码写在类或模块之中,就只有严格模式可用. 考虑到未来所有的代码,其实都是运行在模块之中,所以 ES6 实际上 ...
- python 3.x 学习笔记10 (析构函数and继承)
1.类变量的用途:大家公用的属性,节省开销(内存) 2.析构函数 在实例释放和销毁的时候执行的,通常用于做一些收尾工作,如关闭一些数据库链接和打开的临时文件 3.私有方法两个下划线开头,声明该方法为私 ...
- 新疆大学(新大)OJ xju 1010: 四个年级 C++ STL map 将4层循环优化成2层循环可解
1010: 四个年级 时间限制: 3 Sec 内存限制: 128 MB 题目描述 为了加强全体软件学院的同学的较量,学院想让ACM协会设计一次活动让所以软件学院的同学都加入,并且要实现高年级和低年级 ...
- hiho160周 - 字符串压缩,经典dp
题目链接 小Hi希望压缩一个只包含大写字母'A'-'Z'的字符串.他使用的方法是:如果某个子串 S 连续出现了 X 次,就用'X(S)'来表示.例如AAAAAAAAAABABABCCD可以用10(A) ...
- 解析浏览器和nodejs环境下console.log()的区别
写在前面的 在开发调试过程中,我们经常需要调用console.log 方法来打印出当前变量的值,然而,console.log在浏览器环境下 有时会出现一些异常的现象 开撸代码 在浏览器和nodejs环 ...
- Vue-cli 3.0 构建项目
Vue-cli是vue的一个脚手架,我们可以通过它来构建我们的前端项目 vue-cli3环境配置 //1. 安装nodeJS(已经集成npm) 首先需要安装node环境,可以直接到中文官网http:/ ...
- BZOJ 3881 [Coci2015]Divljak(AC自动机+树状数组)
建立AC自动机然后,加入一个串之后考虑这个串的贡献.我们把这个串扔到AC自动机里面跑.最后对经过每一个点到的这个点在fail树的根的路径上的点有1的贡献.求链的并,我们把这些点按DFS序排序,然后把每 ...
- webpack2.X、Vue学习以及将两者相结合
在家的闲暇时间来完善自己的前端知识. 经过两三天的学习,按照webpack文档学习,vue文档学习,最后实现了两者结合的目标. webpack 按照网站上guide的流程依次学习 1.使用npm安装w ...
- 紫书 例题8-6 UVa 1606(扫描法)
这道题目用扫描法 扫描法:在枚举的过程中维护一些重要的量, 从而简化计算 这道题用到了极角, 叉积, 高一的我表示一脸懵逼 不过自己去百度了一下好像大概看得懂. 这道题我还有一些疑问, 先这样吧 #i ...