In the previous chapter, we have a preliminary understanding of PHP's source directory structure, and this chapter continues to dissect PHP from the dimension of the life cycle.
I. Overview
What is the life cycle? You can think of it as a process of execution, the life cycle of PHP, which is the process from the beginning to the end of execution.
PHP life cycle has five stages, namely module initialization phase, request initialization phase, execution phase, request shutdown phase, module shutdown phase. Only in different SAPI mode, the request is slightly different, such as fastcgi only experienced a module initialization phase, and then all requests only go through the request initialization, execution script, request shutdown phase.
After a preliminary understanding of the five phases of the life cycle, let's start with PHP's work before entering the module initialization phase (PHP_MODULE_STARTUP) (this article continues with the PHP7.0.12 version of the CLI mode). Well, let's start now.
Second, source code Analysis 2.1, Sapi_module_struct
The portal file in CLI mode is sapi/cli/php_cli.c
, open the file, navigate to main function main, do you think the structure of the 1180 line appears sapi_module_struct
familiar? This is the previous article SAPI the introduction of the structure, it is the extension of PHP external services key.
//sapi/cli/php_cli.csapi_module_struct *sapi_module = &cli_sapi_module;
Let's take sapi_module_struct
a look at main/SAPI.h
the definition in:
Main/sapi.hstruct _sapi_module_struct {char *name;//name, such as CLI, FPM, etc. char *pretty_name; Easier to understand name Int (*startup) (struct _sapi_module_struct *sapi_module); function int (*shutdown) (struct _sapi_module_struct *sapi_module) called when the module is started; function int (*activate) (void) called at the end of the module; function int (*deactivate) (void) to be called when processing the request; function size_t (*ub_write) (const char *STR, size_t str_length) to invoke when the request is processed; For output data Void (*flush) (void *server_context); Refresh Cache zend_stat_t * (*get_stat) (void); Determines whether the executed file has execute permissions char * (*getenv) (char *name, size_t Name_len); Gets the function pointer of the function variable void (*sapi_error) (int type, const char *error_msg, ...); Error handling function pointer int (*header_handler) (Sapi_header_struct *sapi_header, Sapi_header_op_enum op, sapi_headers_struct *sapi_ headers); function int (*send_headers) called when the header () is called (Sapi_headers_struct *sapi_headers); function pointer to send all headers void (*send_header) (Sapi_header_struct *sapi_header, void *server_context); A function pointer that sends a header size_t (*read_post) (cHar *buffer, size_t count_bytes); Gets the function pointer of the data in the HTTP POST char * (*read_cookies) (void); Get cookie Void (*register_server_variables) (Zval *track_vars_array); The function pointer Void (*log_message) (char *message) that gets the variable from the $_server; Output error message function pointer double (*get_request_time) (void); Gets the request time function pointer void (*terminate_process) (void); Call exit when the function pointer char *php_ini_path_override; The INI file of PHP is a duplicate address void (*block_interruptions) (void); void (*unblock_interruptions) (void); void (*default_post_reader) (void); Responsible for parsing post data Void (*treat_data) (int arg, char *str, Zval *destarray); Processing of data char *executable_location; The geographical location of the execution of int php_ini_ignore; Whether to use any INI configuration file int php_ini_ignore_cwd; php.ini Int (*GET_FD) (int *fd) that ignores the current path; Gets the function pointer int (*FORCE_HTTP_10) (void) of the FD that executes the file; Enforces the use of the http1.0 version of the function pointer Int (*GET_TARGET_UID) (uid_t *); Gets the UID function pointer Int (*GET_TARGET_GID) (gid_t *) of the executing program; Gets the GID function pointer of the executor unsigned int (*input_filter) (int arg, char *var, Char **val, size_T Val_len, size_t *new_val_len); A function pointer that filters the input, such as filling an input parameter into an auto global variable $_get, $_post, $_cookie Void (*ini_defaults) (HashTable *configuration_hash); int phpinfo_as_text; Whether to output phpinfo information//default INI configuration function pointer, the INI configuration information in Hashtable char *ini_entries; The INI configuration included with the execution allows php-d to set the const zend_function_entry *additional_functions; Some functions that are unique to each SAPI module are registered, such as the CLI's cli_get_process_title unsigned int (*input_filter_init) (void);}
Each of the schemas under SAPI implements the struct, such as in the CLI:
//sapi/cli/php_cli.cstatic sapi_module_struct cli_sapi_module = { "cli", /* name */ "Command Line Interface", /* pretty name */ ......}
In FPM:
//sapi/fpm/fpm/fpm_main.cstatic sapi_module_struct cgi_sapi_module = { "fpm-fcgi", /* name */ "FPM/FastCGI", /* pretty name */ ......}
The same definition is also found in Litespeed:
//sapi/litespeed/lsapi_main.cstatic sapi_module_struct lsapi_sapi_module ={ "litespeed", "LiteSpeed V6.10", ......}
2.2, Sapi_startup
We continue to look down, after the initialization of a series of variables, the function is called in 1302 rows sapi_startup
.
//sapi/cli/php_cli.csapi_startup(sapi_module);
This function defines, that is, the sapi_globals_struct
SG macro that we often say, its main function is to save the basic information of the request, such as server information, header, encoding, etc.
//main/SAPI.htypedef struct _sapi_globals_struct { void *server_context; sapi_request_info request_info; sapi_headers_struct sapi_headers; int64_t read_post_bytes; unsigned char post_read; unsigned char headers_sent; zend_stat_t global_stat; char *default_mimetype; char *default_charset; HashTable *rfc1867_uploaded_files; zend_long post_max_size; int options; zend_bool sapi_started; double global_request_time; HashTable known_post_content_types; zval callback_func; zend_fcall_info_cache fci_cache;} sapi_globals_struct;
2.3, Sapi_module->startup
We continue to look down and sapi_module
call the startup
function:
//sapi/cli/php_cli.cif (sapi_module->startup(sapi_module) == FAILURE) { exit_status = 1; goto out;}
The sapi_module_struct
corresponding hook functions defined in the CLI are then called startup
php_cli_startup
:
//sapi/cli/php_cli.cstatic sapi_module_struct cli_sapi_module = { "cli", /* name */ "Command Line Interface", /* pretty name */ php_cli_startup, /* startup */ ......}
Continue to follow up, and the function is php_cli_startup
called again php_module_startup
:
//sapi/cli/php_cli.cstatic int php_cli_startup(sapi_module_struct *sapi_module) /* {{{ */{ if (php_module_startup(sapi_module, NULL, 0)==FAILURE) { return FAILURE; } return SUCCESS;}
2.4, Php_module_startup
is not very familiar, this is not the module initialization stage function! It turned out that it took so long to get to our key point, the module initialization stage content is more, we through the next chapter detailed analysis.
//main/main.cint php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint num_additional_modules){ zend_utility_functions zuf; zend_utility_values zuv; int retval = SUCCESS, module_number=0; /* for REGISTER_INI_ENTRIES() */ char *php_os; zend_module_entry *module; ...}
Note: The code I posted in this article identifies the location of the file, and we can see that it was executed in the SAPI directory before the beginning of the five life cycle of PHP, and from Php_module_struct, which was the module initialization phase, was executed to the main directory. This means that the first phase of the PHP life cycle starts with the main directory.