Taking the MOD_PHP5 module of Apache2 as an example, the hooks are registered through the Php_ap2_register_hook () function, and Pre_config,post_config,child_init are the start hooks, which are called when the server is started. Handler is a request for hooks, hooks to Apache. It's natural to do different jobs when Apache starts and requests.
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);}
In the Php_apache_server_startup
Static Intphp_apache_server_startup (apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, Server_rec *s) {void *data = N Ull;const char *userdata_key = "apache2hook_post_config";/* Apache would load, unload and then reload a DSO module. This * prevents us from starting PHP until the second load. */apr_pool_userdata_get (&data, Userdata_key, S->process->pool); if (data = = NULL) {/* We must use Set () here and *not* SETN (), otherwise the * static string pointed to by Userdata_key'll be mapped * to a different location when the D So was reloaded and the * Pointers won ' t match, causing get () to return NULL if * We expected it to return non-null. */apr_pool_userdata_set ((const void *) 1, Userdata_key, Apr_pool_cleanup_null, S->process->pool); return OK;} /* Set up our overridden path. */if (apache2_php_ini_path_override) {apache2_sapi_module.php_ini_path_override = Apache2_php_ini_path_override;} #ifdef Ztstsrm_startup (1, 1, 0, NULL); #endifsapi_startup (&apache2_sapi_module);//Complete SAPI startup, initialize global variables, etc. apache2_sapi_module.startup (&apache2_sapi_module);//By calling the _sapi_module_struct startup function, Register Apache SAPI Module A series of functions Apr_pool_cleanup_register (pconf, NULL, Php_apache_server_shutdown, apr_pool_cleanup_null); Php_apache_add_version (pconf); return OK;}
It then calls Php_module_startup to launch PHP as a module of Apache, initializing some PHP states, functions, and so on. The code to be used in this article is:
int Php_module_startup (sapi_module_struct *sf, Zend_module_entry *additional_modules, uint num_additional_modules) { Zend_utility_functions Zuf; Omit part of the Code php_output_startup ();//Initialize the output function of php zuf.error_function = php_error_cb;zuf.printf_function = php_printf; zuf.write_function = php_body_write_wrapper;//php default output function zuf.fopen_function = Php_fopen_wrapper_for_zend; Zuf.message_handler = Php_message_handler_for_zend;zuf.block_interruptions = sapi_module.block_interruptions; Zuf.unblock_interruptions = Sapi_module.unblock_interruptions;zuf.get_configuration_directive = php_get_ Configuration_directive_for_zend;zuf.ticks_function = Php_run_ticks;zuf.on_timeout = Php_on_timeout;zuf.stream_ Open_function = Php_stream_open_for_zend;zuf.vspprintf_function = Vspprintf;zuf.getenv_function = sapi_getenv; Zuf.resolve_path_function = Php_resolve_path_for_zend;zend_startup (&zuf, NULL tsrmls_cc);.. Omit part of code}
Phpapi void Php_output_startup (void)->static void php_output_init_globals (Php_output_globals *output_globals_p TSRMLS_DC)
At this point, the default series of PHP output functions are:
static void Php_output_init_globals (Php_output_globals *output_globals_p tsrmls_dc) {OG (php_body_write) = Php_default _output_func;og (Php_header_write) = Php_default_output_func;og (Implicit_flush) = 0;og (output_start_filename) = NULL ; OG (Output_start_lineno) = 0;}
/* {{{php_default_output_func */phpapi int php_default_output_func (const char *STR, UINT Str_len tsrmls_dc) {fwrite (str, 1, Str_len, stderr);//default output to standard error/* See http://support.microsoft.com/kb/190351 */#ifdef Php_win32fflush (stderr); # Endifreturn Str_len;}
This occurs when Apache starts the process of initializing PHP, and obviously the output function is incorrect during each request. The trace function php_handler->php_apache_request_ctor->php_request_startup-> php_output_activate, in this function:
Phpapi void Php_output_activate (tsrmls_d) {og (php_body_write) = php_ub_body_write;//output function OG (php_header_write) = Sapi_ Module.ub_write;og (Ob_nesting_level) = 0;og (Ob_lock) = 0;og (Disable_output) = 0;og (Output_start_filename) = NULL;OG ( Output_start_lineno) = 0;} PHPAPI int php_ub_body_write (const char *STR, UINT str_length tsrmls_dc) {int result = 0;if (SG (Request_info)). headers_only {if (SG (headers_sent)) {return 0;} Php_header (Tsrmls_c); Zend_bailout ();} if (Php_header (Tsrmls_c)) {if (zend_is_compiling (Tsrmls_c)) {OG (Output_start_filename) = Zend_get_compiled_filename ( Tsrmls_c); OG (Output_start_lineno) = Zend_get_compiled_lineno (Tsrmls_c);} else if (zend_is_executing (tsrmls_c)) {og (output_start_filename) = Zend_get_executed_filename (tsrmls_c); OG (output_ Start_lineno) = Zend_get_executed_lineno (Tsrmls_c);} OG (php_body_write) = php_ub_body_write_no_header;//output function re-assignment result = Php_ub_body_write_no_header (str, str_length TSRMLS_CC);} return result;} PHPAPI int Php_ub_body_write_no_header (const char *STR,UINT Str_length tsrmls_dc) {int result;if (OG (disable_output)) {return 0;} result = og (php_header_write) (str, str_length TSRMLS_CC);//actually call OG (php_header_write) is sapi_module.ub_ Write as Apache function if (OG (Implicit_flush)) {Sapi_flush (tsrmls_c);} return result;}
The result is clear, when PHP starts, the output function points to the FD is stderr, at each request, and then point the function pointer to the Apache output function.
In the Zend_startup, there will be:
Zend_api zend_write_func_t zend_write;zend_write = (zend_write_func_t) utility_functions->write_function;
In practical use, echo, for example, will eventually invoke:
Zend_api int Zend_print_zval (zval *expr, int indent)/* {{*/{return zend_print_zval_ex (zend_write, expr, indent);//zend _write is a pointer function that is actually called}
Think about PHP in the request, you can dynamically specify the output function, so that more convenient SAPI layer of the interface to write, the output function of the control power on the server side only reasonable, but PHP in its own packaging a lot of layers, do not know whether the name and age-old relationship.