亚洲精品中文字幕无乱码_久久亚洲精品无码AV大片_最新国产免费Av网址_国产精品3级片

php語言

細(xì)讀PHP的生命周期

時間:2024-11-02 04:47:55 php語言 我要投稿
  • 相關(guān)推薦

細(xì)讀PHP的生命周期

  導(dǎo)語:PHP是一種通用開源腳本語言。語法吸收了C語言、Java和Perl的特點(diǎn),利于學(xué)習(xí),使用廣泛,主要適用于Web開發(fā)領(lǐng)域。下面我們來看看PHP的生命周期,希望對大家有所幫助。

  啟動

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

  初始化若干全局變量

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

  初始化若干常量

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

  初始化ZEND引擎和核心組件

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

  解析php.ini

  php_init_config函數(shù)的作用是讀取php.ini文件,設(shè)置配置參數(shù),加載zend擴(kuò)展并注冊PHP擴(kuò)展函數(shù)。此函數(shù)分為如下幾步:初始化參數(shù)配置表,調(diào)用當(dāng)前模式下的ini初始化配置,比如CLI模式下,會做如下初始化:

  INI_DEFAULT("report_zend_debug", "0");

  INI_DEFAULT("display_errors", "1");

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

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

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

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

  在準(zhǔn)備完查找路徑后,PHP會判斷現(xiàn)在的ini路徑(php_ini_file_name)是否為文件和是否可打開。如果這里ini路徑是文件并且可打開,則會使用此文件, 也就是CLI模式下通過-c參數(shù)指定的ini文件的優(yōu)先級是最高的,其次是PHPRC指定的文件,第三是在搜索路徑中查找php-%sapi-module-name%.ini文件(如CLI模式下應(yīng)該是查找php-cli.ini文件),最后才是搜索路徑中查找php.ini文件。

  全局操作函數(shù)的初始化

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

  php_startup_sapi_content_types函數(shù)用來初始化SAPI對于不同類型內(nèi)容的處理函數(shù),這里的處理函數(shù)包括POST數(shù)據(jù)默認(rèn)處理函數(shù)、默認(rèn)數(shù)據(jù)處理函數(shù)等。

  初始化靜態(tài)構(gòu)建的模塊和共享模塊(MINIT)

  php_register_internal_extensions_func函數(shù)用來注冊靜態(tài)構(gòu)建的模塊,也就是默認(rèn)加載的模塊,我們可以將其認(rèn)為為內(nèi)置模塊。在PHP5.3.0版本中內(nèi)置的模塊包括PHP標(biāo)準(zhǔn)擴(kuò)展模塊(/ext/standard/目錄,這里是我們用的最頻繁的函數(shù),比如字符串函數(shù),數(shù)學(xué)函數(shù),數(shù)組操作函數(shù)等等),日歷擴(kuò)展模塊、FTP擴(kuò)展模塊、 session擴(kuò)展模塊等。這些內(nèi)置模塊并不是一成不變的,在不同的PHP模板中,由于不同時間的需求或其它影響因素會導(dǎo)致這些默認(rèn)加載的模塊會變化,比如從代碼中我們就可以看到mysql、xml等擴(kuò)展模塊曾經(jīng)或?qū)頃鳛閮?nèi)置模塊出現(xiàn)。

  模塊初始化會執(zhí)行兩個操作:

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

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

  在注冊了靜態(tài)構(gòu)建的模塊后,PHP會注冊附加的模塊,不同的模式下可以加載不同的模塊集,比如在CLI模式下是沒有這些附加的模塊的。

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

  在所有的模塊都注冊后,PHP會馬上執(zhí)行模塊初始化操作(zend_startup_modules)。它的整個過程就是依次遍歷每個模塊,調(diào)用每個模塊的模塊初始化函數(shù),也就是在本小節(jié)前面所說的用宏P(guān)HP_MINIT_FUNCTION包含的內(nèi)容。

  禁用函數(shù)和類

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

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

  ACTIVATION

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

  激活ZEND引擎

  gc_reset函數(shù)用來重置垃圾收集機(jī)制,當(dāng)然這是在PHP5.3之后才有的。

  init_compiler函數(shù)用來初始化編譯器,比如將編譯過程中在放opcode的數(shù)組清空,準(zhǔn)備編譯時用來的數(shù)據(jù)結(jié)構(gòu)等等。

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

  激活SAPI

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

  在處理了post數(shù)據(jù)后,PHP會通過sapi_module.read_cookies讀取cookie的值,在CLI模式下,此函數(shù)的實(shí)現(xiàn)為sapi_cli_read_cookies,而在函數(shù)體中卻只有一個return NULL;

  如果當(dāng)前模式下有設(shè)置activate函數(shù),則運(yùn)行此函數(shù),激活SAPI,在CLI模式下此函數(shù)指針被設(shè)置為NULL。

  環(huán)境初始化

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

  以$_COOKIE為例,php_default_treat_data函數(shù)會對依據(jù)分隔符,將所有的cookie拆分并賦值給對應(yīng)的變量。

  模塊請求初始化

  PHP通過zend_activate_modules函數(shù)實(shí)現(xiàn)模塊的請求初始化,也就是我們在圖中看到Call each extension’s RINIT。此函數(shù)通過遍歷注冊在module_registry變量中的所有模塊,調(diào)用其RINIT方法實(shí)現(xiàn)模塊的請求初始化操作。

  運(yùn)行

  php_execute_script函數(shù)包含了運(yùn)行PHP腳本的全部過程。

  當(dāng)一個PHP文件需要解析執(zhí)行時,它可能會需要執(zhí)行三個文件,其中包括一個前置執(zhí)行文件、當(dāng)前需要執(zhí)行的主文件和一個后置執(zhí)行文件。非當(dāng)前的兩個文件可以在php.ini文件通過auto_prepend_file參數(shù)和auto_append_file參數(shù)設(shè)置。如果將這兩個參數(shù)設(shè)置為空,則禁用對應(yīng)的執(zhí)行文件。

  對于需要解析執(zhí)行的文件,通過zend_compile_file(compile_file函數(shù))做詞法分析、語法分析和中間代碼生成操作,返回此文件的所有中間代碼。如果解析的文件有生成有效的中間代碼,則調(diào)用zend_execute(execute函數(shù))執(zhí)行中間代碼。如果在執(zhí)行過程中出現(xiàn)異常并且用戶有定義對這些異常的處理,則調(diào)用這些異常處理函數(shù)。在所有的操作都處理完后,PHP通過EG(return_value_ptr_ptr)返回結(jié)果。

  DEACTIVATION

  PHP關(guān)閉請求的過程是一個若干個關(guān)閉操作的集合,這個集合存在于php_request_shutdown函數(shù)中。這個集合包括如下內(nèi)容:

  調(diào)用所有通過register_shutdown_function()注冊的函數(shù)。這些在關(guān)閉時調(diào)用的函數(shù)是在用戶空間添加進(jìn)來的。一個簡單的例子,我們可以在腳本出錯時調(diào)用一個統(tǒng)一的函數(shù),給用戶一個友好一些的頁面,這個有點(diǎn)類似于網(wǎng)頁中的404頁面。

  執(zhí)行所有可用的__destruct函數(shù)。這里的析構(gòu)函數(shù)包括在對象池(EG(objects_store)中的所有對象的析構(gòu)函數(shù)以及EG(symbol_table)中各個元素的析構(gòu)方法。

  將所有的輸出刷出去。

  發(fā)送HTTP應(yīng)答頭。這也是一個輸出字符串的過程,只是這個字符串可能符合某些規(guī)范。

  遍歷每個模塊的關(guān)閉請求方法,執(zhí)行模塊的請求關(guān)閉操作,這就是我們在圖中看到的Call each extension’s RSHUTDOWN。

  銷毀全局變量表(PG(http_globals))的變量。

  通過zend_deactivate函數(shù),關(guān)閉詞法分析器、語法分析器和中間代碼執(zhí)行器。

  調(diào)用每個擴(kuò)展的post-RSHUTDOWN函數(shù)。只是基本每個擴(kuò)展的post_deactivate_func函數(shù)指針都是NULL。

  關(guān)閉SAPI,通過sapi_deactivate銷毀SG(sapi_headers)、SG(request_info)等的內(nèi)容。

  關(guān)閉流的包裝器、關(guān)閉流的過濾器。

  關(guān)閉內(nèi)存管理。

  重新設(shè)置最大執(zhí)行時間

  結(jié)束

  最終到了要收尾的地方了。

  flush

  sapi_flush將最后的內(nèi)容刷新出去。其調(diào)用的是sapi_module.flush,在CLI模式下等價于fflush函數(shù)。

  關(guān)閉ZEND引擎

  zend_shutdown將關(guān)閉ZEND引擎。

  此時對應(yīng)圖中的流程,我們應(yīng)該是執(zhí)行每個模塊的關(guān)閉模塊操作。在這里只有一個zend_hash_graceful_reverse_destroy函數(shù)將module_registry銷毀了。當(dāng)然,它最終也是調(diào)用了關(guān)閉模塊的方法的,其根源在于在初始化module_registry時就設(shè)置了這個hash表析構(gòu)時調(diào)用ZEND_MODULE_DTOR宏。而ZEND_MODULE_DTOR宏對應(yīng)的是module_destructor函數(shù)。在此函數(shù)中會調(diào)用模塊的module_shutdown_func方法,即PHP_RSHUTDOWN_FUNCTION宏產(chǎn)生的那個函數(shù)。

  在關(guān)閉所有的模塊后,PHP繼續(xù)銷毀全局函數(shù)表,銷毀全局類表、銷售全局變量表等。通過zend_shutdown_extensions遍歷zend_extensions所有元素,調(diào)用每個擴(kuò)展的shutdown函數(shù)。

【細(xì)讀PHP的生命周期】相關(guān)文章:

php與php MySQL之間的關(guān)系10-03

什么是PHP PHP與ASP比較09-18

php正則去掉php注釋07-30

PHP中php://input和$-POST的區(qū)別08-26

PHP試題07-04

PHP是做什么的 如何學(xué)習(xí)PHP06-18

Java的線程的生命周期簡述08-10

產(chǎn)品生命周期階段的判定08-20

php的發(fā)展歷程08-23

PHP網(wǎng)站模板精選06-13