php运行生命周期--请求初始化php_request_startup

时间:2022-07-24
本文章向大家介绍php运行生命周期--请求初始化php_request_startup,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

php_request_startup主要有以下几个阶段

函数

说明

php_output_activate

重置输出全局变量,初始化输出相关堆栈

zend_activate(核心)

初始化Zend引擎

sapi_activate

调用sapi_module里面的active方法

zend_signal_activate

信号处理

zend_set_timeout

设置超时时间

php_hash_environment

初始化相关全局变量

zend_activate_modules

循环调用request_startup_func激活模块

php_output_activate

重新为output_globals分配内存,初始化与输出处理程序相关的堆栈,并将OG宏的flags设置为激活状态。

PHPAPI int php_output_activate(void)
{
#ifdef ZTS
    memset((*((void ***) ZEND_TSRMLS_CACHE))[TSRM_UNSHUFFLE_RSRC_ID(output_globals_id)], 0, sizeof(zend_output_globals));
#else
    memset(&output_globals, 0, sizeof(zend_output_globals));
#endif

    zend_stack_init(&OG(handlers), sizeof(php_output_handler *));
    OG(flags) |= PHP_OUTPUT_ACTIVATED;

    return SUCCESS;
}

zend_activate

gc_reset()重置垃圾回收 init_compiler()初始化编译器,(词法语法解析) init_executor()初始化执行器 startup_scanner()初始化扫描器

sapi_activate

对SG宏内的一些变量进行初始化,并调用当前sapi_module_struct中定义的钩子函数activate()以及input_filter_init(),但是在cli模式下,这两个钩子函数都没有实现,返回了null

SAPI_API void sapi_activate(void)
{
    zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct), (void (*)(void *)) sapi_free_header, 0);
    SG(sapi_headers).send_default_content_type = 1;

    /*
    SG(sapi_headers).http_response_code = 200;
    */
    SG(sapi_headers).http_status_line = NULL;
    SG(sapi_headers).mimetype = NULL;
    SG(headers_sent) = 0;
    ZVAL_UNDEF(&SG(callback_func));
    SG(read_post_bytes) = 0;
    SG(request_info).request_body = NULL;
    SG(request_info).current_user = NULL;
    SG(request_info).current_user_length = 0;
    SG(request_info).no_headers = 0;
    SG(request_info).post_entry = NULL;
    SG(request_info).proto_num = 1000; /* Default to HTTP 1.0 */
    SG(global_request_time) = 0;
    SG(post_read) = 0;
    /* It's possible to override this general case in the activate() callback, if necessary. */
    if (SG(request_info).request_method && !strcmp(SG(request_info).request_method, "HEAD")) {
        SG(request_info).headers_only = 1;
    } else {
        SG(request_info).headers_only = 0;
    }
    SG(rfc1867_uploaded_files) = NULL;

    /* Handle request method */
    if (SG(server_context)) {
        if (PG(enable_post_data_reading)
        &&  SG(request_info).content_type
        &&  SG(request_info).request_method
        && !strcmp(SG(request_info).request_method, "POST")) {
            /* HTTP POST may contain form data to be processed into variables
             * depending on given content type */
            sapi_read_post_data();
        } else {
            SG(request_info).content_type_dup = NULL;
        }

        /* Cookies */
        SG(request_info).cookie_data = sapi_module.read_cookies();
    }
    if (sapi_module.activate) {
        sapi_module.activate();
    }
    if (sapi_module.input_filter_init) {
        sapi_module.input_filter_init();
    }
}

zend_signal_activate

对应的宏是空的,没有做什么事情

zend_set_timeout

通过settimer的方式实现

php_hash_environment

为http_globals分配内存,初始化auto_globals,解析请求参数并存放到全局变量中。

PHPAPI int php_hash_environment(void)
{
    memset(PG(http_globals), 0, sizeof(PG(http_globals)));
    zend_activate_auto_globals();
    if (PG(register_argc_argv)) {
        php_build_argv(SG(request_info).query_string, &PG(http_globals)[TRACK_VARS_SERVER]);
    }
    return SUCCESS;
}

zend_activate_modules

该函数通过遍历注册在module_registry的所有模块,调用每个模块的钩子函数request_startup()进行初始化。

ZEND_API void zend_activate_modules(void) /* {{{ */
{
    zend_module_entry **p = module_request_startup_handlers;

    while (*p) {
        zend_module_entry *module = *p;

        if (module->request_startup_func(module->type, module->module_number)==FAILURE) {
            zend_error(E_WARNING, "request_startup() for %s module failed", module->name);
            exit(1);
        }
        p++;
    }
}