<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      PHP7內核(五):系統分析生命周期

      上篇文章講述了模塊初始化階段之前的準備工作,本篇我來詳細介紹PHP生命周期的五個階段。

      一、模塊初始化階段

      我們先來看一下該階段的每個函數的作用。

      image

      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;
      

      執行階段調用示意圖:
      image

      四、請求關閉階段

      請求關閉階段主要內容是調用各模塊的關閉函數和析構函數、輸出緩沖區內容、調用各擴展的鉤子函數RSHUTDOWN、關閉編譯器和執行器以及還原PHP配置等。

      image

      五、模塊關閉階段

      雖然請求關閉和模塊關閉看起來是兩個截然不同的階段,但閱讀完源碼后發現并看不出兩個階段的區別。它的主要作用是調用模塊的flush函數、清理符號表、銷毀全局變量、關閉內存管理和垃圾回收、關閉輸出等。

      image

      posted @ 2018-09-05 22:51  MARIOOW  閱讀(1195)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 日韩亚洲视频一区二区三区| 中文字幕av日韩有码| 国产日韩一区二区四季| 一区二区中文字幕久久| 欧美成人精品一级在线观看| 蜜芽亚洲AV无码精品国产午夜| 加勒比亚洲天堂午夜中文| 亚洲日韩一区二区| www国产精品内射熟女| 和田市| 国产18禁一区二区三区| 宾馆人妻4P互换视频| 久久精品人人槡人妻人人玩AV| 成人av专区精品无码国产| 麻豆国产成人AV在线播放| 亚洲自在精品网久久一区| 黑森林福利视频导航| 四虎国产精品永久在线| 亚洲日韩国产二区无码| 亚洲国产成人久久一区久久| 四房播色综合久久婷婷| 久久99国产亚洲高清观看首页| 香港日本三级亚洲三级| 韩国三级+mp4| 青青草原网站在线观看| 伦伦影院午夜理论片| 国产精品天天狠天天看| 四虎成人精品国产永久免费| 中文字幕亚洲人妻一区| 亚洲欧美日韩精品久久| 欧美丰满熟妇vaideos| 亚洲精品国偷自产在线99人热| 国产成人永久免费av在线| 无码AV无码免费一区二区| 忘忧草影视| 天天综合色天天综合色h| 国产人与zoxxxx另类| 国产精品一区二区国产馆| 久青草国产在视频在线观看| 欧美www在线观看| 妺妺窝人体色www婷婷|