PHP7 程式碼執行過程
PHP 是解釋型語言,其執行過程需先編譯成中間程式碼,再經由特定的虛擬機器,翻譯成特定的指令被執行。其執行過程如下:
PHP 程式碼 => Token => 抽象語法樹 => Opcodes => 執行
各個步驟內容如下:
- 原始碼通過詞法分析得到 Token
Token 是 PHP 程式碼被切割成的有意義的標識。PHP7 一共有 137 種 Token,在zend_language_parser.h 檔案中做了定義。
- 基於語法分析器將 Token 轉換成抽象語法樹(AST)
Token 就是一個個的詞塊,但是單獨的詞塊不能表達完整的語義,還需要藉助一定的規則進行組織串聯。所以就需要語法分析器根據語法匹配Token,將 Token 進行串聯。語法分析器串聯完 Token 後的產物就是抽象語法樹(AST,Abstract Syntax Tree)。
AST 是 PHP7 版本的新特性,之前版本的 PHP 程式碼的執行過程中是沒有生成 AST 這一步的。它的作用主要是實現了PHP編譯器和直譯器的解耦,提升了可維護性。
- 將語法樹轉換成 Opcode
需要將語法樹轉換成Opcode,才能被引擎直接執行。
- 執行 Opcodes
opcodes 是 opcode 的集合形式,是 PHP 執行過程中的中間程式碼。PHP工程優化措施中有一個比較常見的“開啟 opcache”,指的技術這裡將 opcodes 進行快取。通過省去從原始碼到 opcode 的階段,引擎直接執行快取好的 opacode,以提升效能。
PHP7 核心架構
要把這張圖印在腦海裡
- zend引擎
詞法/語法分析、AST編譯和 opcodes 的執行均在 Zend 引擎中實現。此外,PHP的變數設計、記憶體管理、程式管理等也在引擎層實現。
- PHP層
zend 引擎為 PHP 提供基礎能力,而來自外部的互動則需要通過 PHP 層來處理。
- SAPI
server API 的縮寫,其中包含了場景的 cli SAPI 和 fpm SAPI。只要遵守定義好的 SAPI 協議,外部模組便可與PHP完成互動。
- 擴充套件部分
依據 zend 引擎提供的核心能力和介面規範,可以進行開發擴充套件。
PHP 7 原始碼結構
php 7 的原始碼主要目錄有:sapi 、Zend、main、ext 和 TSRM 這幾個。
- sapi目錄
sapi目錄是對輸入和輸出層的抽象,是PHP提供對外服務的規範。
幾種常用的 SAPI:
1)apache2handler: Apache 擴充套件,編譯後生成動態連結庫,配置到Apache下。當有 http 請求到 Apache 時,根據配置會呼叫此動態連結庫來執行PHP程式碼,完成與PHP的互動。
2)cgi-fcgi: 編譯後生成支援 CGI 協議的可執行程式,webserver(如NGINX)通過 CGI 協議把請求傳給CGI程式,CGI 程式根據請求執行相應程式碼後將執行結果返回給 webserver。
3)fpm-fcgi: fpm是 FastCGI 程式管理器。以 NGINX 伺服器為例,當有請求傳送到 NGINX 伺服器,NGINX 按照 FastCGI 協議把請求交給 php-fpm 程式處理。
4)cli: PHP的命令列互動介面
- Zend 目錄
Zend 目錄是 PHP 的核心程式碼。PHP中的記憶體管理,垃圾回收、程式管理、變數、陣列實現等均在該目錄的原始碼裡。
- main 目錄
main目錄是SAPI層和Zend層的黏合劑。Zend 層實現了 PHP 指令碼的編譯和執行,sapi 層實現了輸入和輸出的抽象,main目錄則在它們中間起著承上啟下的作用。承上,解析 SAPI 的請求,分析要執行的指令碼檔案和引數;啟下,呼叫 zend 引擎之前,完成必要的模組初始化等工作。
- ext目錄
ext 是 PHP 擴充套件相關的目錄,常用的 array、str、pdo 等系列函式都在這裡定義。
- TSRM
TSRM(Thread Safe Resource Manager)——執行緒安全資源管理器, 是用來保證資源共享的安全。
參考資料
《PHP7 底層設計與原始碼實現》