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

    原文地址:

  • 相关阅读:
    eclipse export runnable jar(导出可执行jar包) runnable jar可以执行的
    mave常用指令
    771. Jewels and Stones珠宝数组和石头数组中的字母对应
    624. Maximum Distance in Arrays二重数组中的最大差值距离
    724. Find Pivot Index 找到中轴下标
    605. Can Place Flowers零一间隔种花
    581. Shortest Unsorted Continuous Subarray连续数组中的递增异常情况
    747. Largest Number At Least Twice of Others比所有数字都大两倍的最大数
    643. Maximum Average Subarray I 最大子数组的平均值
    414. Third Maximum Number数组中第三大的数字
  • 原文地址:https://www.cnblogs.com/lalalagq/p/9962057.html
Copyright © 2020-2023  润新知