PHP7 源碼總體框架

1、PHP7語言執行原理php

經常使用的高級語言有不少種,根據運行的方式不一樣,大致分爲兩種:編譯型語言和解釋型語言。git

編譯是指在應用源程序執行以前,就將程序源代碼「翻譯」成彙編語言,而後進一步根據軟硬件環境編譯成目標文件。通常稱完成編譯工做的工具爲編譯器github

而解釋型語言,在程序運行時才被「翻譯」爲機器語言。可是執行一次「翻譯」一次,因此執行效率較低。解釋器的工做就是解釋型語言中,負責「翻譯」源代碼的程序。web

對於一段C語言代碼,須要通過預編譯、編譯、彙編和連接,才能成爲可執行的二進制文件。apache

以C語言爲表明的編譯型語言,代碼發生更新都要通過以上步驟。api

 

編譯型語言的執行示意:
 
 
對編譯型語言與解釋型語言的區別的理解,立足於源代碼被編譯成目標平臺CPU指令的時機。對於編譯型語言,編譯結果已是針對當前CPU體系的指令;而解釋型語言,須要先編譯成中間代碼,再經由該解釋型語言的特定虛擬機,翻譯成特定CPU體系的指令被執行。解釋型語言是在運行過程當中,翻譯爲目標平臺的指令。常說解釋型語言「慢」,主要也是慢在這裏。
在PHP 7中,源代碼首先進行詞法分析,將源代碼切割爲多個字符串單元,分割後的字符串稱爲Token。而一個一個獨立的Token是沒法表達完整語義的,需通過語法分析階段,將Token轉換爲抽象語法樹(簡稱AST)。以後,抽象語法樹被轉換爲機器指令執行。在PHP中,這些指令稱爲opcode。
 

第1步:源碼經過詞法分析獲得Token。數組

第2步:基於語法分析器生成抽象語法樹(AST)。緩存

第3步:抽象語法樹轉換爲opcodes(opcode指令集合),PHP解釋執行opcodes。安全

1.Token服務器

Token是PHP代碼被切割成的有意義的標識。PHP提供了token_get_all()函數來獲取PHP代碼被切割後的Token.。

二維數組的每一個成員數組的第一個值爲Token對應的枚舉值。第二個值爲Token對應的原始字符串內容。第三個值爲代碼對應的行號。

可見,Token就是一個個的「詞塊」,可是單獨存在的詞塊不能表達完整的語義,還須要藉助規則進行組織串聯。語法分析器就是這個組織者。它會檢查語法,匹配Token,對Token進行關聯。

2.AST

AST是PHP 7版本新特性。在這以前的版本中,PHP代碼的執行過程當中是沒有生成AST這一步的。

AST的節點分爲多種類型,對應着PHP語法。

PHP-Parser工具,它能夠用來查看PHP代碼生成的AST。

注意 PHP-Parser是PHP 7內核做者之一Nikic編寫的將PHP源碼生成AST的工具。源碼見https://github.com/nikic/PHP-Parser

3.opcodes

opcode只是單條指令,opcodes是opcode的集合形式,是PHP執行過程當中的中間代碼。opcode生成以後由虛擬機執行。

PHP工程優化措施中有一個比較常見的「開啓opcache」,指的就是這裏的opcodes的緩存(opcodes cache)。經過省去從源碼到opcode的階段,引擎能夠直接執行緩存的opcode,以此

提高性能。

藉助vld插件,能夠直觀地看到一段PHP代碼生成的opcode。

opcode是PHP 7定義的一組指令標識,指令對應着相應的handler(處理函數)。當虛擬機調用opcode,會找到opcode背後的處理函數,執行真正的處理。

 

2、內核架構

Zend引擎中包含了編譯器和解釋器,從PHP代碼到opcode的執行,均由Zend引擎完成。

Zend引擎除了實現了PHP的核心功能,還提供了一套接口,讓PHP能夠在更多的場景中使用,如命令行環境、Web環境等。

該架構圖大體分爲四大部分。

1)Zend引擎:前文介紹的詞法/語法分析、AST編譯和opcodes的執行均在Zend引擎中實現。此外,PHP的變量設計、內存管理、進程管理等也在引擎層實現。引擎爲PHP提供了基礎服務,PHP的可靠性和高性能都依賴引擎的基礎支撐。同時,Zend引擎的可擴展性,仍是PHP得以大規模應用的重要緣由之一。

2)PHP層:Zend引擎爲PHP提供基礎能力(如內存分配和回收),而來自外部的交互則須要經過PHP層來處理。

3)SAPI:SAPI是Server API的縮寫,其中包含了常見的cli SAPI和fpm SAPI。PHP定義好輸入/輸出規範,依據此規範與PHP交互的一方均可以稱爲Server。

4)擴展部分:Zend引擎提供了核心能力和接口規範。在此基礎上開發的擴展,爲PHP代碼的性能和功能的多樣性提供了更豐富的選項。

 

3、PHP源碼目錄

sapi目錄源碼

sapi目錄是對輸入和輸出層的抽象,是PHP提供對外服務的規範。

PHP程序的輸入能夠是來自於命令行的標準輸入,也能夠是來自基於cgi/fastcgi協議的網絡請求。同理,輸出能夠寫到命令行的標準輸出,也能夠做爲基於cgi/fastcgi協議的網絡響應返回給客戶端。

命令行模式對應的是二進制程序bin/php;內置模塊的模式不須要提供二進制程序,做爲普通函數供Apache或任意C/C++程序來調用便可;CGI模式對應的是二進制程序bin/cgi;FastCGI模式對應的是二進制程序sbin/php-fpm。

幾種經常使用的SAPI。

1)apache2handler:Apache擴展,編譯後生成動態連接庫,配置到Apache下,當有http請求到Apache時,根據配置會調用此動態連接庫,執行PHP代碼,完成與PHP的交互。

2)cgi-fcgi:編譯後生成支持CGI協議的可執行程序,webserver(一般爲Apache或Nginx)經過CGI協議把請求傳給CGI進程,執行代碼將結果返回給webserver,退出進程。

3)fpm-fcgi:fpm全稱爲FastCGI Process Manager,PHP官方提供的FastCGI進程管理器。以Nginx服務器爲例,當有http協議請求發送到Nginx服務器,Nginx按照FastCGI協議把請求交給php-fpm進程處理。

4)cli:Command Line Interface的簡稱,PHP的命令行交互接口。

Zend目錄源碼

Zend目錄是PHP的核心代碼。

1.內存管理模塊

2.垃圾回收

3.數組實現

main目錄源碼

main目錄是SAPI層和Zend層的黏合劑。

Zend層實現了PHP腳本的編譯和執行,sapi層實現了輸入和輸出的抽象,main目錄則起到了承上啓下的做用:承上,解析SAPI的請求,分析要執行的腳本文件和參數;啓下,調用Zend引擎以前,完成必要的初始化等工做。

ext目錄源碼

ext是PHP擴展相關的目錄,經常使用的array、str、pdo等系列函數都在這裏定義。

TSRM目錄源碼

PHP在早期更多的是單個進程、單線程模型運行的,在後期才引入了線程安全機制ZTS(Zend Thread Safety)。

TSRM是Thread Safe Resource Manager的縮寫——線程安全資源管理器。

線程安全機制主要爲了保證共享資源的安全。PHP的線程安全機制簡潔直觀——在多線程環境下,爲每一個線程提供獨立的全局變量副本。具體實施是經過TSRM爲每一個線程分配(分配前加鎖)一個獨立ID(自增)做爲當前線程的全局變量內存區索引,在之後的全局變量訪問中,實現線程之間的徹底獨立。

相關文章
相關標籤/搜索