跟厂长学PHP7内核(五):系统分析生命周期

上篇文章讲述了模块初始化阶段之前的准备工作,本篇我来详细介绍PHP生命周期的五个阶段。

一、模块初始化阶段

我们先来看一下该阶段的每个函数的作用。

1.1、sapi_initialize_request_empty函数

// main/SAPI.c
SAPI_API void sapi_initialize_empty_request(void)
{
    SG(server_context) = NULL;
    SG(request_info).request_method = NULL;
    SG(request_info).auth_digest = SG(request_info).auth_user = SG(request_info).auth_password = NULL;
    SG(request_info).content_type_dup = NULL;
}

这个函数主要为前面定义的SG宏中的成员变量进行初始化。

1.2、sapi_activate函数

// main/SAPI.c
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_status_line = NULL;
    SG(sapi_headers).mimetype = NULL;
    SG(headers_sent) = 0;
    ......
    /* Handle request method */
    if (SG(server_context)) {
        ......

        if (sapi_module.activate) {
            sapi_module.activate();
        }
    }
    if (sapi_module.input_filter_init) {
        sapi_module.input_filter_init();
    }
}

函数的前半部分主要还是对SG宏的成员变量进行初始化。后半部分先是调用了sapi_module_struct内部实现的activate函数,又调用了input_filter_init函数,但是在CLI模式并没有实现这两个函数,只是返回了NULL。代码如下:

NULL,                           /* activate */

1.3、php_output_startup函数

//main/output.c
PHPAPI void php_output_startup(void)
{
    ZEND_INIT_MODULE_GLOBALS(output, php_output_init_globals, NULL);
    zend_hash_init(&php_output_handler_aliases, 8, NULL, NULL, 1);
    zend_hash_init(&php_output_handler_conflicts, 8, NULL, NULL, 1);
    zend_hash_init(&php_output_handler_reverse_conflicts, 8, NULL, reverse_conflict_dtor, 1);
    php_output_direct = php_output_stdout;
}

我们先来看ZEND_INIT_MODULE_GLOBALS宏做了什么事情:

#define ZEND_INIT_MODULE_GLOBALS(module_name, globals_ctor, globals_dtor)       globals_ctor(&module_name##_globals);

由代码得知,该宏只是做了一层替换,替换后的内容为:

php_output_init_globals(&output_globals);

php_output_init_globals函数又做了什么呢?

//main/output.c
static inline void php_output_init_globals(zend_output_globals *G)
{
    ZEND_TSRMLS_CACHE_UPDATE();
    memset(G, 0, sizeof(*G));
}

该函数通过memset函数对output_globals进行了内存相关的初始化,我们可以在main/php_output.h中的155行找到它的宏定义OG。

//main/php_output.h
# define OG(v) (output_globals.v)

OG对应的结构体是php_output_init_globals的入参zend_output_globals,在这里花了些时间,因为没找到定义在哪里,最后发现它也是通过宏定义替换得来的,代码如下:

//main/php_output.h
ZEND_BEGIN_MODULE_GLOBALS(output)
    zend_stack handlers;
    php_output_handler *active;
    php_output_handler *running;
    const char *output_start_filename;
    int output_start_lineno;
    int flags;
ZEND_END_MODULE_GLOBALS(output)

看似是定义了一个结构体,但是代码中又出现了两个宏,我们再来瞅瞅这两个宏是干嘛的:

//Zend/zend_API.h
#define ZEND_BEGIN_MODULE_GLOBALS(module_name)          typedef struct _zend_##module_name##_globals {
#define ZEND_END_MODULE_GLOBALS(module_name)            } zend_##module_name##_globals;

原来只是做了个替换而已,替换后的代码如下:

//这个是意淫出来的代码
typedef struct _zend_output_globals {
    zend_stack handlers;
    php_output_handler *active;
    php_output_handler *running;
    const char *output_start_filename;
    int output_start_lineno;
    int flags;
} zend_output_globals

这才是zend_output_globals最纯粹的定义,写的很是骚气,差点看断片。这样看来我们的OG宏对应的就是这个结构体了,姑且认为它是PHP输出相关的结构体。我们继续往下看:

zend_hash_init(&php_output_handler_aliases, 8, NULL, NULL, 1);
zend_hash_init(&php_output_handler_conflicts, 8, NULL, NULL, 1);
zend_hash_init(&php_output_handler_reverse_conflicts, 8, NULL, reverse_conflict_dtor, 1);
php_output_direct = php_output_stdout;

接下来又对三个HashTable进行了初始化,初始化完成后,将php_output_direct指针指向了php_output_stdout函数。php_output_stdout函数的作用是调用fwrite函数,输出字符串到stdout中。代码如下:

//main/output.c
static size_t php_output_stdout(const char *str, size_t str_len)
{
    fwrite(str, 1, str_len, stdout);
    return str_len;
}

1.4、php_startup_ticks函数

int php_startup_ticks(void)
{
    zend_llist_init(&PG(tick_functions), sizeof(struct st_tick_function), NULL, 1);
    return SUCCESS;
}

这里又出现了一个PG宏,来看下它的定义

# define PG(v) (core_globals.v)

PG对应的结构体是core_globalscore_globals又对应_php_core_globals,代码如下

extern ZEND_API struct _php_core_globals core_globals;

php_core_globals顾名思义,就是php核心的全局变量,定义很多PHP相关的参数,比如内存上限、是否显示错误信息、上传文件大小限制、输入输出编码、禁用的函数等等,这里不再赘述,感兴趣的同学可以去看一下源码。

//main/php_globals.h
struct _php_core_globals {
    zend_bool implicit_flush;

    zend_long output_buffering;

    zend_bool sql_safe_mode;
    zend_bool enable_dl;
    ......
};

php_startup_ticks函数就是对PG宏的成员变量tick_functions进行初始化。

1.5、gc_globals_ctor函数

ZEND_API void gc_globals_ctor(void)
{
    gc_globals_ctor_ex(&gc_globals);
}

这里又出现了一个gc_globals,它是与垃圾回收相关的结构体,这段代码是对gc_globals进行初始化。

//Zend/zend_gc.c
typedef struct _zend_gc_globals {
    zend_bool         gc_enabled;
    zend_bool         gc_active;
    zend_bool         gc_full;

    gc_root_buffer   *buf;              /* preallocated arrays of buffers   */
    ......

} zend_gc_globals;

1.6、zend_startup函数

++start_memory_manager++:初始化内存管理器,对结构体alloc_globals进行初始化。

++virtual_cwd_startup++:virtual_cwd_startup初始化了cwd_globals,根据源码可以看出成员变量都与realpath_cache有关,realpath_cache是什么呢?我们平时在写代码的时候,经常会使用include、include_once、require、require_once等语句导入文件,如果每次使用这些语句都要去对应的目录中寻找目标文件,势必会降低性能,所以官方加入了缓存,以便PHP再次使用时不必到include_path中查找,加快PHP的执行速度。

//Zend/zend_virtual_cwd.c
typedef struct _virtual_cwd_globals {
    cwd_state cwd;
    zend_long                   realpath_cache_size;
    zend_long                   realpath_cache_size_limit;
    zend_long                   realpath_cache_ttl;
    realpath_cache_bucket *realpath_cache[1024];
} virtual_cwd_globals;

++zend_startup_extensions_mechanism++。启动扩展机制,初始化zend_extensions结构体。

int zend_startup_extensions_mechanism()
{
    /* Startup extensions mechanism */
    zend_llist_init(&zend_extensions, sizeof(zend_extension), (void (*)(void *)) zend_extension_dtor, 1);
    last_resource_number = 0;
    return SUCCESS;
}

++提供编译与执行入口++

zend_compile_file = compile_file;
zend_execute_ex = execute_ex;

++zend_init_opcodes_handlers++。初始化Zend虚拟机的handler

++初始化CG、EG++。初始化CG(function_table)、CG(class_table)、CG(auto_globals)、EG(zend_constants)。

GLOBAL_FUNCTION_TABLE = (HashTable *) malloc(sizeof(HashTable));
GLOBAL_CLASS_TABLE = (HashTable *) malloc(sizeof(HashTable));
GLOBAL_AUTO_GLOBALS_TABLE = (HashTable *) malloc(sizeof(HashTable));
GLOBAL_CONSTANTS_TABLE = (HashTable *) malloc(sizeof(HashTable));

++ini_scanner_globals_ctor++。初始化ini_scanner_globals

++php_scanner_globals_ctor++。初始化language_scanner_globals

++zend_set_default_compile_time_values++。设置了编译相关的配置。

//Zend/zend.c
static void zend_set_default_compile_time_values(void) /* {{{ */
{
    /* default compile-time values */
    CG(short_tags) = short_tags_default;
    CG(compiler_options) = compiler_options_default;
}

++EG(error_reporting)++。EG宏就是executor_globals,Zend执行器相关的全局变量,在这里对我们熟知的error_reporting进行配置。

//Zend/zend_globals.h
struct _zend_executor_globals {
    zval uninitialized_zval;
    zval error_zval;

    /* symbol table cache */
    zend_array *symtable_cache[SYMTABLE_CACHE_SIZE];
    zend_array **symtable_cache_limit;
    zend_array **symtable_cache_ptr;
    ......
}

++zend_interned_strings_init++。初始化内部字符串。

//Zend/zend_string.c
void zend_interned_strings_init(void)
{
#ifndef ZTS
    zend_string *str;

    zend_hash_init(&CG(interned_strings), 1024, NULL, _str_dtor, 1);
    ......
}

++zend_startup_builtin_functions++。初始化内部函数。

//Zend/zend_builtin_functions.c
int zend_startup_builtin_functions(void) /* {{{ */
{
    zend_builtin_module.module_number = 0;
    zend_builtin_module.type = MODULE_PERSISTENT;
    return (EG(current_module) = zend_register_module_ex(&zend_builtin_module)) == NULL ? FAILURE : SUCCESS;
}

++zend_register_standard_constants++。注册常量,比如E_ERROR、E_WARNING、E_NOTICE、E_CORE_ERROR等。

//Zend/zend_constants.c
void zend_register_standard_constants(void)
{
    REGISTER_MAIN_LONG_CONSTANT("E_ERROR", E_ERROR, CONST_PERSISTENT | CONST_CS);
    REGISTER_MAIN_LONG_CONSTANT("E_RECOVERABLE_ERROR", E_RECOVERABLE_ERROR, CONST_PERSISTENT | CONST_CS);
    REGISTER_MAIN_LONG_CONSTANT("E_WARNING", E_WARNING, CONST_PERSISTENT | CONST_CS);
    ......
}

++zend_register_auto_global++。将GLOBALS加入CG(auto_globals)。

//Zend/zend.c
zend_register_auto_global(zend_string_init("GLOBALS", sizeof("GLOBALS") - 1, 1), 1, php_auto_globals_create_globals);

++zend_init_rsrc_plist++。初始化持久化符号表。

int zend_init_rsrc_plist(void)
{
    zend_hash_init_ex(&EG(persistent_list), 8, NULL, plist_entry_destructor, 1, 0);
    return SUCCESS;
}

++zend_init_exception_op++。初始化EG(exception_op)。

++zend_init_call_trampoline_op++。初始化EG(call_trampoline_op)。

++zend_ini_startup++。初始化与php.ini解析相关的变量。

//Zend/zend_ini.c
ZEND_API int zend_ini_startup(void) /* {{{ */
{
    registered_zend_ini_directives = (HashTable *) malloc(sizeof(HashTable));

    EG(ini_directives) = registered_zend_ini_directives;
    EG(modified_ini_directives) = NULL;
    EG(error_reporting_ini_entry) = NULL;
    zend_hash_init_ex(registered_zend_ini_directives, 128, NULL, free_ini_entry, 1, 0);
    return SUCCESS;
}

1.7、zend_register_list_destructors_ex函数

初始化析构函数

//Zend/zend_list.c
ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, const char *type_name, int module_number)
{
    zend_rsrc_list_dtors_entry *lde;
    zval zv;

    lde = malloc(sizeof(zend_rsrc_list_dtors_entry));
    lde->list_dtor_ex = ld;
    lde->plist_dtor_ex = pld;
    lde->module_number = module_number;
    lde->resource_id = list_destructors.nNextFreeElement;
    lde->type_name = type_name;
    ZVAL_PTR(&zv, lde);

    if (zend_hash_next_index_insert(&list_destructors, &zv) == NULL) {
        return FAILURE;
    }
    return list_destructors.nNextFreeElement-1;
}

1.8、php_binary_init函数

获取PHP执行的二进制路径

static void php_binary_init(void)
{
    char *binary_location;
#ifdef PHP_WIN32
    binary_location = (char *)malloc(MAXPATHLEN);
    if (GetModuleFileName(0, binary_location, MAXPATHLEN) == 0) {
        free(binary_location);
        PG(php_binary) = NULL;
    }
#else
    if (sapi_module.executable_location) {
        binary_location = (char *)malloc(MAXPATHLEN);
        if (!strchr(sapi_module.executable_location, '/')) {
            char *envpath, *path;
            int found = 0;
            ......
}

1.9、php_output_register_constants函数

初始化输出相关的预定义常量

//main/output.c
PHPAPI void php_output_register_constants(void)
{
    REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_START", PHP_OUTPUT_HANDLER_START, CONST_CS | CONST_PERSISTENT);
    REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_WRITE", PHP_OUTPUT_HANDLER_WRITE, CONST_CS | CONST_PERSISTENT);
    REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_FLUSH", PHP_OUTPUT_HANDLER_FLUSH, CONST_CS | CONST_PERSISTENT);
    REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CLEAN", PHP_OUTPUT_HANDLER_CLEAN, CONST_CS | CONST_PERSISTENT);
    REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_FINAL", PHP_OUTPUT_HANDLER_FINAL, CONST_CS | CONST_PERSISTENT);
    REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CONT", PHP_OUTPUT_HANDLER_WRITE, CONST_CS | CONST_PERSISTENT);
    REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_END", PHP_OUTPUT_HANDLER_FINAL, CONST_CS | CONST_PERSISTENT);

    REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_CLEANABLE", PHP_OUTPUT_HANDLER_CLEANABLE, CONST_CS | CONST_PERSISTENT);
    REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_FLUSHABLE", PHP_OUTPUT_HANDLER_FLUSHABLE, CONST_CS | CONST_PERSISTENT);
    REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_REMOVABLE", PHP_OUTPUT_HANDLER_REMOVABLE, CONST_CS | CONST_PERSISTENT);
    REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_STDFLAGS", PHP_OUTPUT_HANDLER_STDFLAGS, CONST_CS | CONST_PERSISTENT);
    REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_STARTED", PHP_OUTPUT_HANDLER_STARTED, CONST_CS | CONST_PERSISTENT);
    REGISTER_MAIN_LONG_CONSTANT("PHP_OUTPUT_HANDLER_DISABLED", PHP_OUTPUT_HANDLER_DISABLED, CONST_CS | CONST_PERSISTENT);
}

1.10、php_rfc1867_register_constants函数

注册文件上传相关的预定义常量

//main/rfc1867.c
void php_rfc1867_register_constants(void) /* {{{ */
{
    REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_OK",         UPLOAD_ERROR_OK, CONST_CS | CONST_PERSISTENT);
    REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_INI_SIZE",   UPLOAD_ERROR_A,  CONST_CS | CONST_PERSISTENT);
    REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_FORM_SIZE",  UPLOAD_ERROR_B,  CONST_CS | CONST_PERSISTENT);
    REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_PARTIAL",    UPLOAD_ERROR_C,  CONST_CS | CONST_PERSISTENT);
    REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_FILE",    UPLOAD_ERROR_D,  CONST_CS | CONST_PERSISTENT);
    REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_TMP_DIR", UPLOAD_ERROR_E,  CONST_CS | CONST_PERSISTENT);
    REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_CANT_WRITE", UPLOAD_ERROR_F,  CONST_CS | CONST_PERSISTENT);
    REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_EXTENSION",  UPLOAD_ERROR_X,  CONST_CS | CONST_PERSISTENT);
}

1.11、php_init_config函数

初始化配置文件php.ini,并通过zend_parse_ini_file解析。

1.12、zend_register_standard_ini_entries函数

初始化ini相关的变量

void zend_register_standard_ini_entries(void) /* {{{ */
{
    int module_number = 0;

    REGISTER_INI_ENTRIES();
}

1.13、php_startup_auto_globals函数

注册我们熟知的全局变量$_GET、$_POST、$_COOKIE等等

//main/php_variables.c
void php_startup_auto_globals(void)
{
    zend_register_auto_global(zend_string_init("_GET", sizeof("_GET")-1, 1), 0, php_auto_globals_create_get);
    zend_register_auto_global(zend_string_init("_POST", sizeof("_POST")-1, 1), 0, php_auto_globals_create_post);
    zend_register_auto_global(zend_string_init("_COOKIE", sizeof("_COOKIE")-1, 1), 0, php_auto_globals_create_cookie);
    zend_register_auto_global(zend_string_init("_SERVER", sizeof("_SERVER")-1, 1), PG(auto_globals_jit), php_auto_globals_create_server);
    zend_register_auto_global(zend_string_init("_ENV", sizeof("_ENV")-1, 1), PG(auto_globals_jit), php_auto_globals_create_env);
    zend_register_auto_global(zend_string_init("_REQUEST", sizeof("_REQUEST")-1, 1), PG(auto_globals_jit), php_auto_globals_create_request);
    zend_register_auto_global(zend_string_init("_FILES", sizeof("_FILES")-1, 1), 0, php_auto_globals_create_files);
}

1.14、php_startup_sapi_content_types函数

初始化针对不同内容类型的处理函数

//main/php_content_types.c
int php_startup_sapi_content_types(void)
{
    sapi_register_default_post_reader(php_default_post_reader);
    sapi_register_treat_data(php_default_treat_data);
    sapi_register_input_filter(php_default_input_filter, NULL);
    return SUCCESS;
}

二、请求初始化阶段

函数 说明
php_output_activate() 重置输出全局变量,初始化输出相关堆栈
zend_activate() 初始化Zend引擎
sapi_activate() 初始化SG宏,调各sapi钩子函数activate
zend_signal_activate() 信号处理
zend_set_timeout() 设置超时时间
php_hash_environment() 初始化PHP请求的全局变量
zend_activate_modules() 调用各扩展定义的request_startup钩子函数

2.1、php_output_activate

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

//main/output.c
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;
}

2.2、zend_activate

zend引擎的初始化,主要作用为重置垃圾回收、初始化编译器、初始化执行器、初始化扫描器。

函数 说明
gc_reset() 重置垃圾回收
init_compiler() 初始化编译器
init_executor() 初始化执行器
startup_scanner() 初始化扫描器

2.3、sapi_activate

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

//main/SAPI.c
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;
    ......
}

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

2.5、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++;
    }
}

三、执行脚本阶段

函数 说明
compile_file() -
open_file_for_scanning() 读取PHP代码内容
zend_parse() 词法语法分析生成AST
init_op_array() 初始化op_array
zend_compile_top_stmt() 将AST转换为op_array
pass_two() 设置op_array中对应zend虚拟机的handler
zend_execute() 执行op_array

执行阶段的入口是php_execute_script函数,该函数又调用了zend_execute_scripts函数,看了这段代码的同学可能会找不到上图表中所提到的compile_file()函数,其实它在模块初始化阶段就已经将compile_file赋值给了zend_compile_file。

//Zend/zend.c
zend_compile_file = compile_file;

执行阶段调用示意图:

四、请求关闭阶段

请求关闭阶段主要内容是调用各模块的关闭函数和析构函数、输出缓冲区内容、调用各扩展的钩子函数RSHUTDOWN、关闭编译器和执行器以及还原PHP配置等。

五、模块关闭阶段

虽然请求关闭和模块关闭看起来是两个截然不同的阶段,但阅读完源码后发现并看不出两个阶段的区别。它的主要作用是调用模块的flush函数、清理符号表、销毁全局变量、关闭内存管理和垃圾回收、关闭输出等。

原文地址:https://www.cnblogs.com/enochzzg/p/9595417.html

时间: 2024-11-08 23:45:19

跟厂长学PHP7内核(五):系统分析生命周期的相关文章

跟厂长学PHP7内核(五):一步步分析生命周期之模块初始化阶段

上篇我们讲到了模块初始化阶段,并得知它是由php_module_startup函数来实现的.该阶段的主要作用是初始化变量.常量:注册各种函数,比如工具.词法.语法函数等:解析配置文件:加载扩展:当然最重要的是计算出PHP二进制程序的路径,现在让我们来研究一下该函数都做了哪些工作. 1.sapi_initialize_request_empty函数 // main/SAPI.c SAPI_API void sapi_initialize_empty_request(void) { SG(serve

跟厂长学PHP内核(四):生命周期之开始前的躁动

上一章我们对PHP的源码目录结构有了初步了解,本章我们继续从生命周期的维度对PHP进行剖析. 一.概览 生命周期是什么呢?你可以把它看作执行过程,PHP的生命周期也就是它从开始执行到结束执行的过程. PHP生命周期有五个阶段,分别为模块初始化阶段.请求初始化阶段.执行阶段.请求关闭阶段.模块关闭阶段.只是不同SAPI模式下,请求的情况略有不同,比如FastCGI下只经历了一次模块初始化阶段,接下来所有请求只经历请求初始化.执行脚本.请求关闭阶段. 在初步了解生命周期的五个阶段之后,我们先来讲述在

Android 进程的五种生命周期学习

本节学习进程的生命周期: Android系统是尽可能的去保护每一个进程,但是最终需要为新的进程,或者很重要的进程释放以前的老进程.为了决定那个进程被保护,那个被杀死.Android系统根据当前进程中组件的状态,以及运行在进行中的组件决定保留那个,杀死那个进程.当然了系统资源短缺时,进程等级低的先杀死,以此类推. android系统中有五种进程等级: 1: 前台进程(前台进程有五种状态,只有其中一种满足就是前台进程,前台进程是很难被杀死的) a:拥有一个正在与用户交互的Activity(此时Act

跟厂长学PHP内核(二):源码分析的环境与工具

本文主要介绍分析源码的方式,其中包含环境的搭建.分析工具的安装以及源码调试的基本操作. 一.工具清单 PHP7.0.12 GDB CLion 二.源码下载及安装 $ wget http://php.net/distributions/php-7.0.12.tar.gz $ tar zxvf php-7.0.12.tar.gz $ cd php-7.0.12/ $ ./configure --prefix=/usr/local/php7 --enable-debug --enable-fpm $

跟厂长学PHP内核(三):源码目录结构

上篇文章我们已经介绍了源码分析工具的安装.配置以及调试方法,本文我们来讲述一下PHP源码的目录结构. 一.目录概览 以php-7.0.12为例,看过源码的同学们应该发现源码目录多达十多个,下面是每个目录的说明. 目录 说明 TSRM 线程相关安全的实现 Zend PHP解析器的核心实现 build linux下编译相关的目录 ext PHP的扩展 main PHP的主要代码 netware 网络目录,socket的定义与实现 pear PHP扩展及应用的代码仓库 sapi PHP的应用层接口 s

android fragment生命周期应用

问题描述 很多时候我们使用fragment都是在viewpager里面嵌套fragment,或者activity下面一个选择标签,在一个container里面添加要切换的几个fragment,这个时候各个fragment之间的切换,他们的生命周期怎样变化呢,下面我们一起来研究下. 解决方案 fragment嵌套在viewpager里面 这个demo是我在csdn上面down下来的,这里贴出原作者.(http://blog.csdn.net/u013758734/article/details/2

Django项目的创建与介绍.应用的创建与介绍.启动项目.pycharm创建启动项目.生命周期.三件套.静态文件.请求及数据.配置Mysql完成数据迁移.单表ORM记录的增删改查

一.Django项目的创建与介绍 ''' 安装Django #在cmd中输入pip3 #出现这个错误Fatal error in launcher: Unable to create process using '"' #可以直接用 python3 -m pip 代替 pip3 #这个问题是pip3 版本过低直接在cmd中执行 python3 -m pip install --upgrade pip 更新pip3 # 在指定解释器环境下安装django 1.11.9 # 在真实python3环境

10天学安卓-第五天

原文:10天学安卓-第五天 经过前几天的练习,相信大家已经对如何做出一个简单的界面有了初步的了解,并且已经做出来一个还不错的天气列表了. 今天大家稍事休息,要练习的内容比较少,着重学习一些理论知识,先理清几个概念. Android系统架构 Android系统本质上是Linux系统,但相对于Linux系统,主要在驱动.性能.内存管理.设备管理等一些部分做了比较多的改动,以更适用于移动设备. 从上图可以看到,Android系统架构为四层,分别是Linux内核.系统运行库.应用程序框架以及应用层,每一

十天学Linux内核之第二天---进程

原文:十天学Linux内核之第二天---进程 都说这个主题不错,连我自己都觉得有点过大了,不过我想我还是得坚持下去,努力在有限的时间里学习到Linux内核的奥秘,也希望大家多指点,让我更有进步.今天讲的全是进程,这点在大二的时候就困惑了我,结果那个时候我就止步不前了,这里主要讲的是为何引入进程.进程在Linux空间是如何实现的,并且描述了所有与进程执行相关的数据结构,最后还会讲到异常和中断等异步执行流程,它们是如何和Linux内核进行交互的,下面我就来具体介绍一下进程的奥妙. 首先我们要明确一个