资讯专栏INFORMATION COLUMN

mod_php模式原理探析

MSchumi / 400人阅读

摘要:模块加载原理的模块可以以静态方式编译到可执行程序中,也可以在运行过程中动态加载以动态链接库的方式。这样在进程运行时一有请求,就可以加载动态链接库文件形式的模块,用来处理请求。

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...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/29620.html

相关文章

  • mod_php模式原理探析

    摘要:模块加载原理的模块可以以静态方式编译到可执行程序中,也可以在运行过程中动态加载以动态链接库的方式。这样在进程运行时一有请求,就可以加载动态链接库文件形式的模块,用来处理请求。 1、PHP与Apache工作模式 在传统的LAMP架构中,PHP与Apache交互时,至少有两种方式『运行PHP』: 使用CGI:Apache发送请求至php-cgi进程,php-cgi进程调用PHP解释器,然...

    cnsworder 评论0 收藏0
  • 深入探析koa之中间件流程控制篇

    摘要:到此为止,我们就基本讲清楚了中的中间件洋葱模型是如何自动执行的。 koa被认为是第二代web后端开发框架,相比于前代express而言,其最大的特色无疑就是解决了回调金字塔的问题,让异步的写法更加的简洁。在使用koa的过程中,其实一直比较好奇koa内部的实现机理。最近终于有空,比较深入的研究了一下koa一些原理,在这里会写一系列文章来记录一下我的学习心得和理解。 在我看来,koa最核心...

    fuchenxuan 评论0 收藏0
  • PHP fastcgi_finish_request 方法

    摘要:介绍每有一个用户请求,都会先要创建的子进程,然后处理请求,处理完后结束这个子进程,这就是模式。当子进程关闭连接时,请求便告处理完成。子进程接着等待并处理来自进程管理器的下一个连接。运行在模式时,提供的方法。 本文介绍,PHP运行在FastCGI模式时,FPM提供的方法:fastcgi_finish_request。 在说这个方法之前,我们先了解PHP有哪些常用的运行模式? PHP运行模...

    macg0406 评论0 收藏0
  • 深入探析koa之异步回调处理篇

    摘要:而之后,我们得到的是一个是一个对象,我们可以使用语句定义回调函数,函数的内容呢,则是将读取到的返回给并继续让从断点处执行。 在上一篇中我们梳理了koa当中中间件的洋葱模型执行原理,并实现了一个可以让洋葱模型自动跑起来的流程管理函数。这一篇,我们再来研究一下koa当中异步回调同步化写法的原理,同样的,我们也会实现一个管理函数,是的我们能够通过同步化的写法来写异步回调函数。 1. 回调金字...

    Drinkey 评论0 收藏0
  • 静态分析安全测试(SAST)优缺点探析

    摘要:许多公司都投资于或之类的静态分析安全测试,解决方案。用静态分析方法确保编程安全一书详细描述了静态分析技术的基本原理。博士将静态分析无法找出的诸多安全问题归为瑕疵,而非程序错误。 静态分析安全测试(SAST)是指不运行被测程序本身,仅通过分析或者检查源程序的语法、结构、过程、接口等来检查程序的正确性,那么采用静分析安全测试的方法有什么优缺点呢,且让小编给你说道说道。 许多公司都投资于 H...

    codeKK 评论0 收藏0

发表评论

0条评论

MSchumi

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<