程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> PHP基礎知識 >> 細讀PHP的生命周期

細讀PHP的生命周期

編輯:PHP基礎知識
 

啟動
 

在調用每個模塊的模塊初始化前,會有一個初始化的過程,它包括:


 

初始化若干全局變量

這裡的初始化全局變量大多數情況下是將其設置為NULL,有一些除外,比如設置zuf(zend_utility_functions),以zuf.printf_function = php_printf為例,這裡的php_printf在zend_startup函數中會被賦值給zend_printf作為全局函數指針使用,而zend_printf函數通常會作為常規字符串輸出使用,比如顯示程序調用棧的debug_print_backtrace就是使用它打印相關信息。


 

初始化若干常量

這裡的常量是PHP自己的一些常量,這些常量要麼是硬編碼在程序中,比如PHP_VERSION,要麼是寫在配置頭文件中,比如PEAR_EXTENSION_DIR,這些是寫在config.w32.h文件中。


 

初始化ZEND引擎和核心組件

前面提到的zend_startup函數的作用就是初始化ZEND引擎,這裡的初始化操作包括內存管理初始化、全局使用的函數指針初始化(如前面所說的zend_printf等),對PHP源文件進行詞法分析、語法分析、中間代碼執行的函數指針的賦值,初始化若干HashTable(比如函數表,常量表等等),為ini文件解析做准備,為PHP源文件解析做准備,注冊內置函數(如strlen、define等),注冊標准常量(如E_ALL、TRUE、NULL等)、注冊GLOBALS全局變量等。


 

解析php.ini

php_init_config函數的作用是讀取php.ini文件,設置配置參數,加載zend擴展並注冊PHP擴展函數。此函數分為如下幾步:初始化參數配置表,調用當前模式下的ini初始化配置,比如CLI模式下,會做如下初始化:

INI_DEFAULT("report_zend_debug", "0");

INI_DEFAULT("display_errors", "1");

不過在其它模式下卻沒有這樣的初始化操作。接下來會的各種操作都是查找ini文件:

判斷是否有php_ini_path_override,在CLI模式下可以通過-c參數指定此路徑(在php的命令參數中-c表示在指定的路徑中查找ini文件)。

如果沒有php_ini_path_override,判斷php_ini_ignore是否為非空(忽略php.ini配置,這裡也就CLI模式下有用,使用-n參數)。

如果不忽略ini配置,則開始處理php_ini_search_path(查找ini文件的路徑),這些路徑包括CWD(當前路徑,不過這種不適用CLI模式)、執行腳本所在目錄、環境變量PATH和PHPRC和配置文件中的PHP_CONFIG_FILE_PATH的值。

在准備完查找路徑後,PHP會判斷現在的ini路徑(php_ini_file_name)是否為文件和是否可打開。如果這裡ini路徑是文件並且可打開,則會使用此文件, 也就是CLI模式下通過-c參數指定的ini文件的優先級是最高的,其次是PHPRC指定的文件,第三是在搜索路徑中查找php-%sapi-module-name%.ini文件(如CLI模式下應該是查找php-cli.ini文件),最後才是搜索路徑中查找php.ini文件。


 

全局操作函數的初始化

php_startup_auto_globals函數會初始化在用戶空間所使用頻率很高的一些全局變量,如:$_GET、$_POST、$_FILES等。這裡只是初始化,所調用的zend_register_auto_global函數也只是將這些變量名添加到CG(auto_globals)這個變量表。

php_startup_sapi_content_types函數用來初始化SAPI對於不同類型內容的處理函數,這裡的處理函數包括POST數據默認處理函數、默認數據處理函數等。

初始化靜態構建的模塊和共享模塊(MINIT)

php_register_internal_extensions_func函數用來注冊靜態構建的模塊,也就是默認加載的模塊,我們可以將其認為為內置模塊。在PHP5.3.0版本中內置的模塊包括PHP標准擴展模塊(/ext/standard/目錄,這裡是我們用的最頻繁的函數,比如字符串函數,數學函數,數組操作函數等等),日歷擴展模塊、FTP擴展模塊、 session擴展模塊等。這些內置模塊並不是一成不變的,在不同的PHP模板中,由於不同時間的需求或其它影響因素會導致這些默認加載的模塊會變化,比如從代碼中我們就可以看到mysql、xml等擴展模塊曾經或將來會作為內置模塊出現。


 

模塊初始化會執行兩個操作:

1. 將這些模塊注冊到已注冊模塊列表(module_registry),如果注冊的模塊已經注冊過了,PHP會報Module XXX already loaded的錯誤。

2. 將每個模塊中包含的函數注冊到函數表( CG(function_table) ),如果函數無法添加,則會報 Unable to register functions, unable to load。

在注冊了靜態構建的模塊後,PHP會注冊附加的模塊,不同的模式下可以加載不同的模塊集,比如在CLI模式下是沒有這些附加的模塊的。

在內置模塊和附加模塊後,接下來是注冊通過共享對象(比如DLL)和php.ini文件靈活配置的擴展。

在所有的模塊都注冊後,PHP會馬上執行模塊初始化操作(zend_startup_modules)。它的整個過程就是依次遍歷每個模塊,調用每個模塊的模塊初始化函數,也就是在本小節前面所說的用宏PHP_MINIT_FUNCTION包含的內容。


 

禁用函數和類

php_disable_functions函數用來禁用PHP的一些函數。這些被禁用的函數來自PHP的配置文件的disable_functions變量。其禁用的過程是調用zend_disable_function函數將指定的函數名從CG(function_table)函數表中刪除。

php_disable_classes函數用來禁用PHP的一些類。這些被禁用的類來自PHP的配置文件的disable_classes變量。其禁用的過程是調用zend_disable_class函數將指定的類名從CG(class_table)類表中刪除。


 

ACTIVATION

在處理了文件相關的內容,PHP會調用php_request_startup做請求初始化操作。請求初始化操作,除了圖中顯示的調用每個模塊的請求初始化函數外,還做了較多的其它工作,其主要內容如下:


 

激活ZEND引擎

gc_reset函數用來重置垃圾收集機制,當然這是在PHP5.3之後才有的。

init_compiler函數用來初始化編譯器,比如將編譯過程中在放opcode的數組清空,准備編譯時用來的數據結構等等。

init_executor函數用來初始化中間代碼執行過程。在編譯過程中,函數列表、類列表等都存放在編譯時的全局變量中,在准備執行過程時,會將這些列表賦值給執行的全局變量中,如:EG(function_table) = CG(function_table); 中間代碼執行是在PHP的執行虛擬棧中,初始化時這些棧等都會一起被初始化。除了棧,還有存放變量的符號表(EG(symbol_table))會被初始化為50個元素的hashtable,存放對象的EG(objects_store)被初始化了1024個元素。 PHP的執行環境除了上面的一些變量外,還有錯誤處理,異常處理等等,這些都是在這裡被初始化的。通過php.ini配置的zend_extensions也是在這裡被遍歷調用activate函數。


 

激活SAPI

sapi_activate函數用來初始化SG(sapi_headers)和SG(request_info),並且針對HTTP請求的方法設置一些內容,比如當請求方法為HEAD時,設置SG(request_info).headers_only=1;此函數最重要的一個操作是處理請求的數據,其最終都會調用sapi_module.default_post_reader。而sapi_module.default_post_reader在前面的模塊初始化是通過php_startup_sapi_content_types函數注冊了默認處理函數為main/php_content_types.c文件中php_default_post_reader函數。此函數會將POST的原始數據寫入$HTTP_RAW_POST_DATA變量。

在處理了post數據後,PHP會通過sapi_module.read_cookies讀取cookie的值,在CLI模式下,此函數的實現為sapi_cli_read_cookies,而在函數體中卻只有一個return NULL;

如果當前模式下有設置activate函數,則運行此函數,激活SAPI,在CLI模式下此函數指針被設置為NULL。


 

環境初始化

這裡的環境初始化是指在用戶空間中需要用到的一些環境變量初始化,這裡的環境包括服務器環境、請求數據環境等。實際到我們用到的變量,就是$_POST、$_GET、$_COOKIE、$_SERVER、$_ENV、$_FILES。和sapi_module.default_post_reader一樣,sapi_module.treat_data的值也是在模塊初始化時,通過php_startup_sapi_content_types函數注冊了默認數據處理函數為main/php_variables.c文件中php_default_treat_data函數。

以$_COOKIE為例,php_default_treat_data函數會對依據分隔符,將所有的cookie拆分並賦值給對應的變量。  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved