深入理解PHP与WEB服务器交互-php教程

资源魔 20 0

  各人都晓得,PHP需求正在详细的WEB效劳器中能力运转,例如Nginx、Apache等,然而PHP是怎么启动,又是怎么正在效劳器中运转,而后二者又是怎么进行交互的呢?

保举教程:php视频教程

1.WEB效劳器挪用PHP接口

  以Apache效劳器为例,咱们看看该效劳器是怎么启动PHP,并挪用PHP中的办法。Apache效劳器启动并运转PHP时,普通是经过mod_php7模块的方式集成(假如是php5.*版本,就是mod_php5模块,模块后缀名依据php版本而定),mod_php7的构造以下(源码门路为php/sapi/apache2handler/mod_php7.c):

AP_MODULE_DECLARE_DATA module php7_module = {
    STANDARD20_MODULE_STUFF,/* 宏,包罗版本,版本,模块索引,模块名,下个模块指针等信息 */
    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,           /* 模块界说的一切指令 */
    php_ap2_register_hook   /* register hooks */
};

  当Apache需求挪用PHP中的办法时,只要要将该申请经过mod_php7模块转达给PHP,PHP层解决完后将数据前往给Apache,整个进程就完结了(增补一下:Apache效劳器启动PHP时,其实有两种加载形式,一种为动态加载,一种为静态加载,方才探讨的mod_php5模块加载形式能够了解为动态加载,也就是需求从新启动Apache效劳器,能力将PHP加载出来;静态加载没有需求重启效劳器,只要要经过发送旌旗灯号的形式将PHP固定的模块加载到效劳器,以达到PHP启动的目的,然而正在进举动态加载前,需求将加载模块编译成静态链接库,而后将其设置装备摆设到效劳器的设置装备摆设文件中)。下面曾经给出Apache正在PHP中的model构造,上面给出Apache效劳器中对应的module构造,以下(该源代码正在Apache中,下同):

struct module_struct {
    int version;
    int minor_version;
    int module_index;
    const char *name;
    void *dynamic_load_handle;
    struct module_struct *next;
    unsigned long magic;
    void (*rewrite_args) (process_rec *process);
    void *(*create_dir_config) (apr_pool_t *p, char *dir);
    void *(*merge_dir_config) (apr_pool_t *p, void *base_conf, void *new_conf);
    void *(*create_server_config) (apr_pool_t *p, server_rec *s);
    void *(*merge_server_config) (apr_pool_t *p, void *base_conf, void *new_conf);
    const co妹妹and_rec *cmds;
    void (*register_hooks) (apr_pool_t *p);
}

  能够看患上出php7_module以及module_struct仍是有很年夜没有同,不外假如看到php7_module.STANDARD20_MODULE_STUFF这个宏的界说形式,你可能就会感觉这两个构造体很像,其实这个宏界说了module_struct中的前8个参数,界说以下:

#define STANDARD20_MODULE_STUFF MODULE_MAGIC_NUMBER_MAJOR, \
    MODULE_MAGIC_NUMBER_MINOR, \
    -1, \
    __FILE__, \
    NULL, \
    NULL, \
    MODULE_MAGIC_COOKIE, \
    NULL /* rewrite args spot */

  而后php7_module.php_dir_cmds界说了模块的一切指令荟萃,详细界说内容以下(代码门路为php/sapi/apache2handler/apache_config.c):

const co妹妹and_rec php_dir_cmds[] =
{
    AP_INIT_TAKE2("php_value", php_apache_value_handler, NULL, OR_OPTIONS, "PHP Value Modifier"),
    AP_INIT_TAKE2("php_flag", php_apache_flag_handler, NULL, OR_OPTIONS, "PHP Flag Modifier"),
    AP_INIT_TAKE2("php_admin_value", php_apache_admin_value_handler, NULL, ACCESS_CONF|RSRC_CONF, "PHP Value Modifier (Admin)
    "),
    AP_INIT_TAKE2("php_admin_flag", php_apache_admin_flag_handler, NULL, ACCESS_CONF|RSRC_CONF, "PHP Flag Modifier (Admin)"),
    AP_INIT_TAKE1("PHPINIDir", php_apache_phpini_set, NULL, RSRC_CONF, "Directory containing the php.ini file"),
    {NULL}
};

  也就是说,PHP层只给Apache提供了上述5个指令,每一个指令的完成源码也正在apache_config.c文件中,最初就剩php7_module.php_ap2_register_hook了,它界说的内容以下(代码门路为php/sapi/apache2handler/mod_php7.c):

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);
}

  php7_module.php_ap2_register_hook函数蕴含4个钩子以及对应的解决函数,pre_config,pre_config、post_config以及child_init是启动钩子,它们是正在效劳器启动时挪用,handler钩子是申请挂钩,它是正在效劳器申请是挪用,经过这些钩子,就能够经过Apache效劳器启动PHP。

   将到这里,想必各人曾经晓得WEB效劳器是若何启动PHP,并挪用PHP中的办法了哈,上面再给各人讲讲PHP是若何挪用WEB效劳器接口的。

2.PHP挪用WEB效劳器接口

  正在讲述这个成绩前,咱们需求理解一下甚么是SAPI。SAPI实际上是与效劳器形象层之间恪守的独特商定,能够这么简略了解,当PHP需求挪用效劳器中的办法,例如肃清缓存,然而肃清缓存的完成办法是正在效劳器中完成,PHP层基本就没有晓得怎样挪用效劳器中的该办法,怎样办?这时候单方需求进行商定,而后效劳器提供一套商定后的接口给PHP,咱们把这些与效劳器形象层之间恪守的独特商定称为SAPI接口。

  成绩来了,关于效劳器Apache,咱们能够提供一套SAPI,然而假如下次又来个其它的效劳器,或许其它的“第三方”,那末咱们是否是也要给他们提供一套独自的SAPI呢?咱们聪慧的PHP开发者一定想到了这一点,即对一切的“第三方”提供一套通用的SAPI接口,然而你能够会问,假如新的“第三方”需求的接口,你的通用SAPI没有支持,那怎样办呢,我的了解是将新的性能增加到PHP的通用SAPI接口中,仅仅是集体见地哈,通用SAPI构造以下(源码门路: php/main/SAPI.h):

struct _sapi_module_struct {
    char *name;         // 名字
    char *pretty_name;  // 更好了解的名字
    int (*startup)(struct _sapi_module_struct *sapi_module);    // 启动函数
    int (*shutdown)(struct _sapi_module_struct *sapi_module);   // 封闭函数
    int (*activate)(TSRMLS_D);           // 激活
    int (*deactivate)(TSRMLS_D);         // 停用
    void (*flush)(void *server_context); // flush
    char *(*read_cookies)(TSRMLS_D);     //read Cookies
    //...
};

  该构造体变量较多,就纷歧一罗列,扼要阐明一下外面的变量:startup函数是当SAPI初始化时会被挪用,shutdown函数是用来开释SAPI的数据构造以及内存等,read_cookie 是正在SAPI激活时被挪用,而后将此函数猎取的值赋值给SG(request_info).cookie_data。那末关于PHP提供的通用SAPI,Apache效劳器又是怎么定制本人的接口呢?详细构造以下(源码门路为php/sapi/apache2handler/sapi_apache2.c):

static sapi_module_struct apache2_sapi_module = {
    "apache2handler",
    "Apache 2.0 Handler",

    php_apache2_startup,            /* startup */
    php_module_shutdown_wrapper,    /* shutdown */

    NULL,                           /* activate */
    NULL,                           /* deactivate */

    php_apache_sapi_ub_write,       /* unbuffered write */
    php_apache_sapi_flush,          /* flush */
    php_apache_sapi_get_stat,       /* get uid */
    php_apache_sapi_getenv,         /* getenv */

    php_error,                      /* error handler */

    php_apache_sapi_header_handler, /* header handler */
    php_apache_sapi_send_headers,   /* send headers handler */
    NULL,                           /* send header handler */

    php_apache_sapi_read_post,      /* read POST data */
    php_apache_sapi_read_cookies,   /* read Cookies */

    php_apache_sapi_register_variables,
    php_apache_sapi_log_message,        /* Log message */
    php_apache_sapi_get_request_time,   /* Request Time */
    NULL,                               /* Child Terminate */

    STANDARD_SAPI_MODULE_PROPERTIES
};

  上述源码目次php/sapi/apache2handler/中,目次php/sapi上面放的都是经过SAPI挪用的“第三方”,该目次构造以下图所示,目次php/sapi/apache2handler中都是与PHP交互的接口,sapi_apache2.c是PHP与Apache商定的SAPI接口文件。

20160821163330607 (1).jpg

  看到这里,各人应该根本分明PHP层是怎么挪用效劳器层的接口,为了强固下面的常识,上面举个栗子,即正在Apache效劳器环境下读取cookie:

SG(request_info).cookie_data = sapi_module.read_cookies(TSRMLS_C);

关于恣意一个效劳器正在加载时,咱们城市指定sapi_module,Apache的sapi_module是apache2_sapi_module,它的read_cookies办法的是php_apache_sapi_read_cookies函数,这样就完成PHP层挪用Apache的接口,是否是很简略呢:)

3.跋文

  这篇博文是我参考《深化了解PHP内核》一书总结的,参考的内容为第二章第二节“SAPI概述”,不外我觉得该书中这局部内容讲的有点绕,我从新编排了,而后提取了外面的重点,并退出集体见地,假如正在该文中有哪些讲的不合错误之处,心愿能帮我指进去,各人独特进步哈,谢谢!

原文地点:https://blog.csdn.net/lml200701158/article/details/52267573

以上就是深化了解PHP与WEB效劳器交互的具体内容,更多请存眷资源魔其它相干文章!

标签: php php开发教程 php开发资料 php开发自学 web服务器

抱歉,评论功能暂时关闭!