首頁 > 後端開發 > php教程 > PHP是怎麼運作的

PHP是怎麼運作的

WBOY
發布: 2016-07-29 09:16:07
原創
1224 人瀏覽過

這篇文章,研究一下PHP程式碼是如何解釋和執行以及PHP腳本運行的生命週期。

概述

PHP服務的啟動。嚴格來說,PHP的相關進程是不需要手動啟動的,它是隨著Apache的啟動而運作的。當然,如果有需要重啟PHP服務的情況下也是可以手動重啟PHP服務的。比如說在有開啟opcode的正式環境更新了程式碼之後,就需要重新啟動PHP才能重新編譯PHP程式碼。

從宏觀來看,PHP內核的實現就是接收輸入的數據,內部做相應的處理然後輸出結果。對PHP核心來說,我們寫的PHP程式碼就是核心接收的輸入數據,PHP核心接收程式碼資料後,對我們寫的程式碼進行程式碼解析和運算執行,最後回傳對應的運算結果。

然而,不同於平常的C語言程式碼,要執行PHP程式碼,首先需要將PHP程式碼「翻譯」成機器語言來執行對應的功能。而要執行「翻譯」這個步驟,就需要PHP核心進行:詞法分析、文法分析等步驟。最後交給PHP內核的Zend Engine進行順次的執行。

詞法分析

將PHP代碼分隔成一個個的「單元」(TOKEN)

語法分析
將「單元」轉換為Zend Engine可執行的操作

Zend Engine
對語法分析得到的操作順次的執行

一切PHP程式(CGI/CLI)的開始都是從SAPI(Server Application Programming Interface)介面開始。 SAPI指的是PHP具體應用的程式介面。例如Apache的mod_php。

PHP開始執行以後會經過兩個主要的階段:處理請求之前的開始階段和請求之後的結束階段。

開始階段

PHP的整個開始階段會經歷模組初始化和模組激活兩個階段。

MINIT

即模組初始化階段,發生在Apache/Nginx啟動以後的整個生命週期或命令列程式整個執行過程中,此階段只進行一次

RINIT
模組激活,發生在請求階段。做一些初始化工作:如註冊常數、定義模組使用的類別等等

模組在實作時可以透過如下巨集來實現這些回呼函數:

PHP_MINIT_FUNCTION(myphpextension)
{
//注册常量或者类等初始化操作
return SUCCESS;
}

PHP_RINIT_FUNCTION(myphpextension)
{
//例如记录请求开始时间
//随后在请求结束的时候记录结束时间。这样我们就能够记录处理请求所花费时间了
return SUCCESS;
}
登入後複製

PHP腳本請求處理完就進入了結束階段,一般腳本執行到結尾或呼叫exit或die函數,PHP就進入結束階段。

結束階段

PHP的結束階段分為停用模組和關閉模組兩個環節。

RSHUTDOWN
停用模組(對應RINIT)

MSHUTDOWN
關閉模組(對應MINIT)

CLI/CGI模式的PHP屬於單一進程的SAPI模式。意思是說,PHP腳本在執行一次之後就關閉掉,所有的變數和函數都不能繼續使用。即在CGI模式下,同一個php檔案的變數在其他php檔案中不能使用。

下面用一個例子來看看單執行緒PHP的SAPI生命週期。

單執行緒SAPI生命週期
如:

php -f test.php
登入後複製

呼叫各個擴充的MINIT 模組初始化
  請求test.php
  》 test.    呼叫各個擴充的RSHUTDOWN 停用模組
執行完t​​est.php後清理變數和記憶體
呼叫各個擴充的MSHUTDOWN 關閉模組
停止PHP執行

以上是一個簡單的執行流程,下面做一些補充。

PHP在呼叫每個模組的模組初始化前,會有一個初始化的過程,包括:

初始化若干全域變數

大多數情況下是將其設為NULL。

初始化若干常數

這裡的常數是PHP本身的一些常數。


初始化Zend引擎和核心元件

這裡的初始化操作包括記憶體管理初始化、全域使用的函數指標初始化,對PHP原始檔進行詞法分析、語法分析、中間程式碼執行的函數指標的賦值,初始化若干HashTable(例如函數表,常量表等等),為ini文件解析做準備,為PHP源文件解析做準備,註冊內置函數、標準常數、GLOBALS全局變量等


解析php.ini

讀取php.ini文件,設置配置參數,載入zend擴充並註冊PHP擴充函數。


全域操作函數的初始化

初始化在用戶空間所使用頻率很高的一些全域變量,如:$_GET、$_POST、$_FILES 等。


初始化靜態建置的模組和共用模組(MINIT)

初始化預設載入的模組。

模組初始化執行操作:
將模組註冊到已註冊模組列表
將每個模組中包含的函數註冊到函數表

禁用函數和類別

會呼叫zend_disable_function函數將PHP的配置文件中的disable_functionsable_functions變數代表的函數從CG(function_table)函數表中刪除。

啟動Zend引擎

使用init_compiler函數來初始化編譯器。

啟動SAPI
使用sapi_activate函數來初始化SG(sapi_headers)和SG(request_info),並且針對HTTP請求的方法設定一些內容。

環境初始化
初始化在使用者控制項需要用到的一些環境變數。包括伺服器環境、請求資料環境等。

模組請求初始化
PHP呼叫zend_activate_modules函數遍歷註冊在module_registry變數中的所有模組,呼叫其RINIT方法方法實現模組的請求初始化操作。

在處理了文件相關的內容後,PHP會呼叫​​php_request_startup做請求初始化操作:

啟動Zend引擎
啟動SAPI
環境初始化
模組請求初始化


就開始執行PHP程式。 PHP透過zend_compile_file做詞法分析、語法分析和中間程式碼產生操作,傳回此檔案的所有中間程式碼。如果解析的檔案有產生有效的中間程式碼,則呼叫zend_excute執行中間程式碼。 。如果在執行過程中出現異常且使用者有定義對這些異常的處理,則呼叫這些異常處理函數。在所有的操作都處理完後,PHP透過EG(return_value_ptr_ptr)傳回結果。


DEACTIVATION(關閉請求)

PHP關閉請求的過程是一個若干個關閉操作的集合,這個集合存在於php_request_shutdown函數中。這個包含:


呼叫所有透過register_shutdown_function()註冊的函數。這些在關閉時呼叫的函數是在用戶空間添加進來的。
執行所有可用的__destruct函數。這裡的析構函數包括在物件池(EG(objects_store)中的所有物件的析構函數以及EG(symbol_table)中各個元素的析構方法。
將所有的輸出刷出去。
發送HTTP應答頭。
銷毀全域變數表(PG(http_globals))的變數。
透過zend_deactivate函數,關閉詞法分析器、語法分析器和中間程式碼執行器。函數指標都是NULL。


結束
PHP結束一個進程是,會呼叫sapi_flush函數將最後的內容刷新出去。 (http://www.php-internals.com/book/)

以上就介紹了PHP是怎麼運作的,包括了方面的內容,希望對PHP教學有興趣的朋友有幫助。


相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板