看看该服务器是怎样启动pHp,并运行pHp中的方法

2023-11-16    分类: 网站建设

1.WEb服务器调用pHp接口

以服务端为例,看看服务端是如何启动pHp并调用pHp中的方法的。服务器启动运行pHp时,一般以模块的形式集成(如果是php5.*版本,则是模块,模块的后缀取决于php版本)。结构如下(源码路径为php/sapi//.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 */
};

当你需要在 pHp 中调用一个方法时,你只需要通过模块将请求传达给 pHp。 pHp层处理完数据后,返回数据,整个过程就结束了。 (另外:服务器启动pHp的时候,其实有两种加载方式,一种是静态加载,一种是动态加载。刚才讨论的模块加载方式可以理解为静态加载,即服务端需要重新启动加载pHp;

动态加载不需要重启服务器。只需通过发送信号将固定的pHp模块加载到服务器即可达到pHp启动的目的。但是在动态加载之前,需要将加载模块编译成动态链接库。然后将其配置到服务器配置文件中)。上面已经给出了pHp中的结构,下面给出了服务器端对应的结构,如下(中间是源码,下同):

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

可以看出and还是有很大区别的,但是如果你看到.UFF宏的定义,你可能会觉得这两个结构很相似。其实这个宏定义了前8个参数,定义如下:

#define STANDARD20_MODULE_STUFF MODULE_MAGIC_NUMbER_MAJOR, 
    MODULE_MAGIC_NUMbER_MINOR, 
    -1, 
    __FILE__, 
    NULL, 
    NULL, 
    MODULE_MAGIC_COOKIE, 
    NULL /* rewrite args spot */

那么。定义了模块的所有指令集php获取apache版本,具体定义内容如下(代码路径为php/sapi//.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层只提供了以上5条指令,每条指令的源码也在.c文件中。最后是.k,其定义如下(代码路径为php/sapi //.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);
}

.k 函数包含 4 个钩子和相应的处理函数,是启动钩子。它们在服务器启动时被调用。钩子是一个请求钩子。在发出服务器请求时调用它。通过这些钩子,你可以通过服务器启动pHp。

我会来的。我想你已经知道WEb服务器如何启动pHp并调用pHp中的方法了。下面我就给大家讲讲pHp是如何调用WEb服务器接口的。

2.pHp 调用WEb服务器接口 在我们讲这个问题之前,我们需要了解什么是SApI。 SApI 实际上是与服务器抽象层观察到的通用协议。很容易理解,当pHp需要调用服务端的某个方法时,比如清除缓存,清除缓存的实现方法是在服务端实现的,pHp层根本不知道。服务端的方法怎么调用,怎么做?

这时候需要双方做一个约定,然后服务器向pHp提供一套约定好的接口。我们将这些与服务器抽象层的通用协议称为 SApI 接口。

问题来了。对于服务器php获取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
    //...
};

这个结构的变量很多,就不一一列举了。我简单解释一下里面的变量:SApI初始化时调用的函数,该函数用于释放SApI的数据结构和内存。它在 SApI 中激活。调用时,则将该函数得到的值赋给SG()。

那么对于pHp提供的通用SApI,服务端如何自定义自己的接口呢?具体结构如下(源码路径为php/sapi//.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//中,php/sapi目录放在通过SApI调用的“第三方”下。目录结构如下图所示,目录php/sapi/都是与pHp交互的接口,.c是pHp与约定的SApI之间的接口文件。

看到这里,大家应该对pHp层如何调用服务层接口有了基本的了解。为了巩固以上知识,下面来个栗子,即在服务器环境下阅读:

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

对于任何一个在加载的时候,我们都会指定它的方法是一个函数,这样就实现了pHp层调用的接口。是不是很简单?

进阶阶段总会有一些问题和瓶颈。写太多业务代码没有方向感。我不知道从哪里开始改进。我整理了一些这方面的资料,包括但不限于:分布式架构、高扩展性、高性能、高并发、服务器性能调优、Tp6、YII2、、、、、优化、脚本、微服务等进阶知识点都可以与您免费分享。需要点这里

最后,祝你在面试中一切顺利,得到你最喜欢的。如果你想和一群3-8年的资深开发者交流学习,你需要

请点击这里 .im

本文名称:看看该服务器是怎样启动pHp,并运行pHp中的方法
文章出自:https://www.cdcxhl.com/news39/294689.html

成都网站建设公司_创新互联,为您提供全网营销推广服务器托管企业网站制作ChatGPT微信公众号外贸建站

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

网站建设网站维护公司