当前位置: 首页 > 后端技术 > PHP

mod_php模式原理解析

时间:2023-03-29 20:31:12 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更容易与ApacheConvenient通信。其中,“运行PHP”是指调用PHP解释器来解释执行PHP脚本。通过php的'php_sapi_name()'函数可以知道当前系统采用哪种工作模式。例如,当值为'apache2handler'时,表示:mod_php模式。2.Apache模块加载原理Apache模块可以静态编译成可执行程序,也可以在Apache运行过程中动态加载(以动态链接库的形式)。这意味着:可以扩展Apache服务器程序而无需从源代码重新编译甚至重新启动它。需要做的就是:向服务器发送一个HUP或AP_SIG_GRACEFUL信号,告诉服务器重新加载模块。关于向Apache发送HUP信号:'向父级发送HUP或重启信号会导致它像在TERM中一样杀死其子级,但父级不会退出。它重新读取其配置文件,并重新打开所有日志文件。然后它产生一组新的孩子并继续提供命中。回到mod_php模块,Apache动态加载模块的过程:首先,在Apache的配置文件http.conf中添加:LoadModulephp7_modulelibexec/apache2/libphp7.so,表示运行时加载的PHP模块的动态链接库文件:libphp7.so。然后通过Apache的内部函数(以Hook的形式)获取动态链接库的内容,将PHP模块的内容加载到内存中的指定变量中。在PHP7源码中,PHP模块(php7_module)的数据结构为:'AP_MODULE_DECLARE_DATAmodulephp7_module={STANDARD20_MODULE_STUFF,/*宏,包括模块结构的前8个字段:版本号,次版本号,模块索引,模块名称、当前模块指针、下一个动态加载模块指针、幻数、rewrite_args函数指针*/create_php_config,/*创建每个目录的配置结构*/merge_php_config,/*合并每个目录的配置结构*/NULL,/*create每个服务器配置结构*/NULL,/*合并每个服务器配置结构*/php_dir_cmds,/*命令apr_table_t*/php_ap2_register_hook/*注册钩子*/};其中php_ap2_register_hook是一系列hook调用:ap_hook_post_config(php_apache_server_startup,NULL,NULL,APR_HOOK_MIDDLE);ap_hook_handler(php_handler,NULL,NULL,APR_HOOK_MIDDLE);#ifdefZEND_SIGNALSap_hook_child_init(zend_signal_init,NULL,NULL,APR_HOOK_MIDDLE);#endifap_hook_child_init(php_apache_child_init,NULL,NULL,APR_HOOK_MIDDLE);}pre_config,post_config,child_init是启动时执行的钩子,Apache服务器启动时会调用它们,PHP解释器会在启动时被调用post_confighookModule(由php_apache_server_startup函数实现:'通过调用sapi_startup启动sapi,通过调用php_apache2_startup注册sapi模块struct(该结构在本节开头有说明),最后调用php_module_startup初始化PHP,在turn初始化ZEND引擎,并在zend_module_struct中填充treat_data成员(通过php_startup_sapi_content_types等')。handler是一个钩子,在请求发出时执行,当Apache服务器处理请求时会调用它。3.ApacheHooking机制:如果在Apache2.4中需要处理一个请求,只需要创建一个钩子(Hook)挂在请求处理程序上即可。钩子,本质上是一条消息:告诉服务器它要么服务于用户发起的请求,要么只是浏览一下。所有Apache模块(包括mod_rewrite、mod_authn_*、mod_proxy等)都是通过挂接到请求过程的各个部分来实现的——挂接到请求过程的特定部分。模块有不同的用途;一些是身份验证/授权处理程序,另一些是文件或脚本处理程序,而一些第三方模块重写URI或代理内容。Apache服务器本身不需要知道每个模块负责处理哪一部分和什么,它只需要:当客户端请求到来时,只需要询问对这个请求是哪个模块“感兴趣”,每个模块只需要选择要不要,如果要,就根据钩子定义的内容进行处理,然后返回给接口。图片来自Apache官网。Apache允许外部模块将自定义函数注入到自己的请求处理循环中,从而参与到Apache的请求处理过程中。通过Hook机制,PHP模块可以负责处理Apache请求处理过程中那些关于php脚本的请求(即负责解释执行php脚本)。具体实现方法参见PHP源码中Apache的ap_hook_post_config钩子的实现:PHP以模块的方式注册到Apache钩子中。这样,每当Apache进程运行时有php请求,就可以加载动态链接库形式的PHP模块(libphp7.so文件)来处理php请求。参考资料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...

最新推荐
猜你喜欢