旗下导航:搜·么
当前位置:网站首页 > PHP问题 > 正文

深切明白PHP道理之PHP与WEB服务器交互【php题目】

作者:搜搜PHP网发布时间:2019-11-26分类:PHP问题浏览:95


导读:人人都晓得,PHP须要在细致的WEB服务器中才运转,比方Nginx、Apache等,然则PHP是怎样启动,又是怎样在服务器中运转,然后二者又是怎样举行交互的呢?1.WEB服...
人人都晓得,PHP须要在细致的WEB服务器中才运转,比方Nginx、Apache等,然则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 command_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 command_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接口文件。

看到这里,人人应当基础清晰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的接口,是否是很简朴呢:)

更多相干题目能够接见ki4网相干教程:https://www.ki4.cn/course/list/29/type/2.html

以上就是深切明白PHP道理之PHP与WEB服务器交互的细致内容,更多请关注ki4网别的相干文章!

标签:PHP