9.PHP内核探索:通过mod_php5支持PHP

来源:互联网 发布:黑客怎么远程控制端口 编辑:程序博客网 时间:2024/05/15 10:39

Apache对PHP的支持是通过Apache的模块mod_php5来支持的。如果希望Apache支持PHP的话,在./configure步骤需要指定--with-apxs2=/usr/local/apache2/bin/apxs 表示告诉编译器通过Apache的mod_php5/apxs来提供对PHP5的解析。

在最后一步make install的时候我们会看到将动态链接库libphp5.so(Apache模块)拷贝到apache2的安装目录的modules目录下,并且还需要在httpd.conf配置文件中添加LoadModule语句来动态将libphp5.so 模块加载进来,从而实现Apache对php的支持。

由于该模式实在太经典了,因此这里关于安装部分不准备详述了,相对来说比较简单。我们知道nginx一般包括两个用途HTTP Server和Reverse Proxy Server(反向代理服务器)。在前端可以部署nginx作为reverse proxy server,后端布置多个Apache来实现机群系统server cluster架构的。

因此,实际生产中,我们仍旧能够保留Apache+mod_php5的经典App Server,而仅仅使用nginx来当做前端的reverse proxy server来实现代理和负载均衡。 因此,建议nginx(1个或者多个)+多个apache的架构继续使用下去。

Apache2的mod_php5模块包括sapi/apache2handler和sapi/apache2filter两个目录 在apache2_handle/mod_php5.c文件中,模块定义的相关代码如下:

AP_MODULE_DECLARE_DATA module php5_module = {    STANDARD20_MODULE_STUFF,        /* 宏,包括版本,小版本,模块索引,模块名,下一个模块指针等信息,其中模块名以__FILE__体现 */    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        /* 注册钩子,此函数通过ap_hoo_开头的函数在一次请求处理过程中对于指定的步骤注册钩子 */};
它所对应的是Apache的module结构,module的结构定义如下:

typedef struct module_struct module;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);}

上面的模块结构与我们在mod_php5.c中所看到的结构有一点不同,这是由于STANDARD20_MODULE_STUFF的原因, 这个宏它包含了前面8个字段的定义。STANDARD20_MODULE_STUFF宏的定义如下:

/** Use this in all standard modules */#define STANDARD20_MODULE_STUFF MODULE_MAGIC_NUMBER_MAJOR, \                MODULE_MAGIC_NUMBER_MINOR, \                -1, \                __FILE__, \                NULL, \                NULL, \                MODULE_MAGIC_COOKIE, \                                NULL      /* rewrite args spot */

在php5_module定义的结构中,php_dir_cmds是模块定义的所有的指令集合,其定义的内容如下:

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

这是mod_php5模块定义的指令表。它实际上是一个command_rec结构的数组。 当Apache遇到指令的时候将逐一遍历各个模块中的指令表,查找是否有哪个模块能够处理该指令, 如果找到,则调用相应的处理函数,如果所有指令表中的模块都不能处理该指令,那么将报错。 如上可见,mod_php5模块仅提供php_value等5个指令。

php_ap2_register_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);    ap_hook_child_init(php_apache_child_init, NULL, NULL, APR_HOOK_MIDDLE);}

以上代码声明了pre_config,post_config,handler和child_init 4个挂钩以及对应的处理函数。 其中pre_config,post_config,child_init是启动挂钩,它们在服务器启动时调用。 handler挂钩是请求挂钩,它在服务器处理请求时调用。其中在post_config挂钩中启动php。 它通过php_apache_server_startup函数实现。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)等。

到这里,我们知道了Apache加载mod_php5模块的整个过程,可是这个过程与我们的SAPI有什么关系呢? mod_php5也定义了属于Apache的sapi_module_struct结构:

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};
这些方法都专属于Apache服务器。以读取cookie为例,当我们在Apache服务器环境下,在PHP中调用读取Cookie时, 最终获取的数据的位置是在激活SAPI时。它所调用的方法是read_cookies。

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函数。 这也是定义SAPI结构的理由:统一接口,面向接口的编程,具有更好的扩展性和适应性。




0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小米商城预售订单点错退款了怎么办 淘宝发布宝贝类目价格受限制怎么办 2019天猫续签评分不达标怎么办 天猫店铺动态不达标不能续签怎么办 京东自提发现货有问题怎么办 京东试用成功商家不发货怎么办 在淘宝主页搜不到我的店铺名怎么办 淘宝发货单号填到别人那去了怎么办 买家申请淘宝介入后同意退款怎么办 淘宝卖家手机版购买装修模块怎么办 天猫店铺和淘宝店铺想要装修怎么办 支付宝转账银行卡卡号错误怎么办 淘宝图片空间照片全部删除了怎么办 我把淘宝图片空间照片删除了怎么办 淘宝发布宝贝怎么没知道品牌怎么办 淘宝提前确认收货了怎么办已经发货 苹果支付安全提示问题忘记了怎么办 没有在规定日期交首付款怎么办 淘宝申请退款又不想退了怎么办 淘宝申请退款后又不想退了怎么办 申请退款后如果不想退了怎么办 世纪明德申请退款但不想退了怎么办 天猫申请换货商家不换怎么办 乐视手机刷机不想清除数据怎么办 捡的苹果手机刷机了要id怎么办 苹果6plus玩王者荣耀卡怎么办 华为荣耀3c的手机内存不足怎么办 红米4x玩王者荣耀卡怎么办 华为手机荣耀10一直重启怎么办 荣耀9青春版老自动重启怎么办 手机开不开机停在华为界面怎么办 华为荣耀9老是反复的重启怎么办 华为荣耀4x老是反复的重启怎么办 手机更新系统后开不了机怎么办 荣耀畅玩7x没有4g网络怎么办 华为4x数字解锁不对中怎么办 华为手机需要解锁后才能刷机怎么办 畅玩6x锁屏壁纸黑了怎么办 指纹密码解锁的手机解不开了怎么办 客户说物流太慢了要退货怎么办 天猫买的手机商家不给发票怎么办