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

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

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

      PHP7內核(四):生命周期之開始前的躁動

      上一章我們對PHP的源碼目錄結構有了初步了解,本章我們繼續從生命周期的維度對PHP進行剖析。

      一、概覽

      生命周期是什么呢?你可以把它看作執行過程,PHP的生命周期也就是它從開始執行到結束執行的過程。

      PHP生命周期有五個階段,分別為模塊初始化階段、請求初始化階段、執行階段、請求關閉階段、模塊關閉階段。只是不同SAPI模式下,請求的情況略有不同,比如FastCGI下只經歷了一次模塊初始化階段,接下來所有請求只經歷請求初始化、執行腳本、請求關閉階段。

      image

      在初步了解生命周期的五個階段之后,我們先來講述在進入模塊初始化階段(php_module_startup)之前PHP所做的工作(本文繼續以PHP7.0.12版本的CLI模式)。好了,我們現在開始。

      二、源碼分析

      2.1、sapi_module_struct

      cli模式下的入口文件是sapi/cli/php_cli.c,打開該文件,定位到主函數main,有沒有覺得1180行出現的結構體sapi_module_struct很眼熟?這就是上篇文章SAPI的介紹中提到到結構體,它是擴展PHP對外服務的關鍵。

      //sapi/cli/php_cli.c
      sapi_module_struct *sapi_module = &cli_sapi_module;
      

      先來看一下sapi_module_structmain/SAPI.h中的定義:

      //main/SAPI.h
      struct _sapi_module_struct {
      	char *name; //名字,如cli、fpm等
      	char *pretty_name;  //更容易理解的名字
      
      	int (*startup)(struct _sapi_module_struct *sapi_module);  //模塊啟動時調用的函數
      	int (*shutdown)(struct _sapi_module_struct *sapi_module);  //模塊結束時調用的函數
      
      	int (*activate)(void);  //處理request時需要調用的函數
      	int (*deactivate)(void);    //處理完request要調用的函數
      
      	size_t (*ub_write)(const char *str, size_t str_length); //用于輸出數據
      	void (*flush)(void *server_context);    //刷新緩存
      	zend_stat_t *(*get_stat)(void); //判斷對執行的文件是否有執行權限
      	char *(*getenv)(char *name, size_t name_len);   //獲取函數變量的函數指針
      
      	void (*sapi_error)(int type, const char *error_msg, ...);   //錯誤處理函數指針
      
      	int (*header_handler)(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers); //調用header()時被調用的函數
      	int (*send_headers)(sapi_headers_struct *sapi_headers); //發送全部header的函數指針
      	void (*send_header)(sapi_header_struct *sapi_header, void *server_context);  //發送某一個header的函數指針
      
      	size_t (*read_post)(char *buffer, size_t count_bytes);  //獲取HTTP POST中數據的函數指針
      	char *(*read_cookies)(void);    //獲取COOKIE
      
      	void (*register_server_variables)(zval *track_vars_array); //從$_SERVER中獲取變量的函數指針
      	void (*log_message)(char *message); //輸出錯誤信息函數指針
      	double (*get_request_time)(void);   //獲取請求時間的函數指針
      	void (*terminate_process)(void);    //調用exit退出時的函數指針
      
      	char *php_ini_path_override;    //PHP的ini文件被復寫的地址
      
      	void (*block_interruptions)(void);  
      	void (*unblock_interruptions)(void);
      
      	void (*default_post_reader)(void);  //負責解析POST數據
      	void (*treat_data)(int arg, char *str, zval *destArray);    //對數據進行處理
      	char *executable_location;  //執行的地理位置
      
      	int php_ini_ignore; //是否不使用任何ini配置文件
      	int php_ini_ignore_cwd; //忽略當前路徑的php.ini
      
      	int (*get_fd)(int *fd); //獲取執行文件的fd的函數指針
      
      	int (*force_http_10)(void); //強制使用http1.0版本的函數指針
      
      	int (*get_target_uid)(uid_t *); //獲取執行程序的uid函數指針
      	int (*get_target_gid)(gid_t *); //獲取執行程序的gid函數指針
      
      	unsigned int (*input_filter)(int arg, char *var, char **val, size_t val_len, size_t *new_val_len); //對輸入進行過濾的函數指針,比如將輸入參數填充到自動全局變量$_GET、$_POST、$_COOKIE中
      
      	void (*ini_defaults)(HashTable *configuration_hash);
      	int phpinfo_as_text; //是否輸出phpinfo信息 //默認的ini配置的函數指針,把ini配置信息在HashTable中
      
      	char *ini_entries; //執行時附帶的ini配置,可以使php -d設置
      	const zend_function_entry *additional_functions; //每個SAPI模塊特有的一些函數注冊,比如cli的cli_get_process_title
      	unsigned int (*input_filter_init)(void);
      }
      

      SAPI下的每一個模式都實現了該結構體,比如在CLI中:

      //sapi/cli/php_cli.c
      static sapi_module_struct cli_sapi_module = {
      	"cli",							/* name */
      	"Command Line Interface",    	/* pretty name */
      	......
      }
      

      FPM中:

      //sapi/fpm/fpm/fpm_main.c
      static sapi_module_struct cgi_sapi_module = {
      	"fpm-fcgi",						/* name */
      	"FPM/FastCGI",					/* pretty name */
          ......
      }
      

      在litespeed中也有相同定義:

      //sapi/litespeed/lsapi_main.c
      static sapi_module_struct lsapi_sapi_module =
      {
          "litespeed",
          "LiteSpeed V6.10",
          ......
      }
      

      2.2、sapi_startup

      我們繼續往下看,在經過一系列變量的初始化后,于1302行又調用了sapi_startup函數。

      //sapi/cli/php_cli.c
      sapi_startup(sapi_module);
      

      該函數定義了sapi_globals_struct,也就是我們常說的SG宏,它的主要作用是保存請求的基本信息,比如服務器信息、header、編碼等。

      //main/SAPI.h
      typedef 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

      我們繼續往下看,sapi_module調用了startup函數:

      //sapi/cli/php_cli.c
      if (sapi_module->startup(sapi_module) == FAILURE) {
      	exit_status = 1;
      	goto out;
      }
      

      然后又調用了CLI在sapi_module_struct中定義的startup對應的鉤子函數php_cli_startup

      //sapi/cli/php_cli.c
      static sapi_module_struct cli_sapi_module = {
      	"cli",							/* name */
      	"Command Line Interface",    	/* pretty name */
      
      	php_cli_startup,				/* startup */
      	......
      }
      

      繼續跟進,php_cli_startup函數中又調用了php_module_startup函數:

      //sapi/cli/php_cli.c
      static 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

      是不是很眼熟,這不就是模塊初始化階段的函數嘛!原來執行了這么久才到我們的關鍵點,模塊初始化階段內容比較多,我們通過下一章進行詳細剖析。

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

      注意:我在本文貼出的代碼都標識了文件位置,我們可以看出來,在PHP五大生命周期開始之前一直都是在sapi目錄中執行的,而從php_module_struct也就是模塊初始化階段開始,才執行到了main目錄,這意味著PHP的生命周期的第一個階段是從main目錄下開始的。

      posted @ 2018-08-31 18:16  MARIOOW  閱讀(1039)  評論(1)    收藏  舉報
      主站蜘蛛池模板: 鲁丝一区鲁丝二区鲁丝三区| 中文字幕国产精品综合| 久久精品久久黄色片看看| 制服丝袜美腿一区二区| 久久精品国产99久久久古代| 午夜福利国产精品视频| 中文日产幕无线码一区中文| 亚洲欧美综合在线天堂| 日韩精品一区二区三区日韩| 国产午夜福利精品久久不卡| 1精品啪国产在线观看免费牛牛| 波多野结衣av高清一区二区三区 | 国产视频最新| 一区二区三区四区精品视频| 国产专区一线二线三线码| a4yy私人毛片| 亚洲 成人 无码 在线观看| 少妇愉情理伦片丰满丰满午夜| 日本一区二区三区在线看| 色九月亚洲综合网| FC2免费人成在线视频| 成人av久久一区二区三区| 久久亚洲av午夜福利精品一区 | а√在线中文网新版地址在线| 你懂的视频在线一区二区| 亚洲大尺度无码专区尤物| 福利在线视频一区二区| 乱色欧美激惰| 丰满的女邻居2| 国产精品天堂蜜av在线播放| 末发育娇小性色xxxxx视频| 日韩中文字幕一二三视频| 国产欧美日韩免费看AⅤ视频| 国产成人精彩在线视频50| 精品亚洲国产成人av在线| 精品久久国产字幕高潮| 国产蜜臀av在线一区二区| 通道| 国精品人妻无码一区免费视频电影 | 亚洲av无码一区二区三区网站| 黑色丝袜脚交视频麻豆|