溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

PHP7 源碼整體框架的示例分析

發(fā)布時(shí)間:2021-02-03 15:00:58 來源:億速云 閱讀:179 作者:小新 欄目:編程語言

這篇文章主要介紹了PHP7 源碼整體框架的示例分析,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

一、PHP7語言執(zhí)行原理

常用的高級(jí)語言有很多種,根據(jù)運(yùn)行的方式不同,大體分為兩種:編譯型語言和解釋型語言。

編譯是指在應(yīng)用源程序執(zhí)行之前,就將程序源代碼“翻譯”成匯編語言,然后進(jìn)一步根據(jù)軟硬件環(huán)境編譯成目標(biāo)文件。一般稱完成編譯工作的工具為編譯器。

而解釋型語言,在程序運(yùn)行時(shí)才被“翻譯”為機(jī)器語言。但是執(zhí)行一次“翻譯”一次,所以執(zhí)行效率較低。解釋器的工作就是解釋型語言中,負(fù)責(zé)“翻譯”源代碼的程序。

對(duì)于一段C語言代碼,需要經(jīng)過預(yù)編譯、編譯、匯編和鏈接,才能成為可執(zhí)行的二進(jìn)制文件。

以C語言為代表的編譯型語言,代碼發(fā)生更新都要經(jīng)過以上步驟。

編譯型語言的執(zhí)行示意:

PHP7 源碼整體框架的示例分析

對(duì)編譯型語言與解釋型語言的區(qū)別的理解,立足于源代碼被編譯成目標(biāo)平臺(tái)CPU指令的時(shí)機(jī)。對(duì)于編譯型語言,編譯結(jié)果已經(jīng)是針對(duì)當(dāng)前CPU體系的指令;而解釋型語言,需要先編譯成中間代碼,再經(jīng)由該解釋型語言的特定虛擬機(jī),翻譯成特定CPU體系的指令被執(zhí)行。解釋型語言是在運(yùn)行過程中,翻譯為目標(biāo)平臺(tái)的指令。常說解釋型語言“慢”,主要也是慢在這里。

在PHP 7中,源代碼首先進(jìn)行詞法分析,將源代碼切割為多個(gè)字符串單元,分割后的字符串稱為Token。而一個(gè)一個(gè)獨(dú)立的Token是無法表達(dá)完整語義的,需經(jīng)過語法分析階段,將Token轉(zhuǎn)換為抽象語法樹(簡(jiǎn)稱AST)。之后,抽象語法樹被轉(zhuǎn)換為機(jī)器指令執(zhí)行。在PHP中,這些指令稱為opcode。

PHP7 源碼整體框架的示例分析

第1步:源碼通過詞法分析得到Token。

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

第3步:抽象語法樹轉(zhuǎn)換為opcodes(opcode指令集合),PHP解釋執(zhí)行opcodes。

PHP7 源碼整體框架的示例分析

1.Token

Token是PHP代碼被切割成的有意義的標(biāo)識(shí)。PHP提供了token_get_all()函數(shù)來獲取PHP代碼被切割后的Token.。

二維數(shù)組的每個(gè)成員數(shù)組的第一個(gè)值為Token對(duì)應(yīng)的枚舉值。第二個(gè)值為Token對(duì)應(yīng)的原始字符串內(nèi)容。第三個(gè)值為代碼對(duì)應(yīng)的行號(hào)。

可見,Token就是一個(gè)個(gè)的“詞塊”,但是單獨(dú)存在的詞塊不能表達(dá)完整的語義,還需要借助規(guī)則進(jìn)行組織串聯(lián)。語法分析器就是這個(gè)組織者。它會(huì)檢查語法,匹配Token,對(duì)Token進(jìn)行關(guān)聯(lián)。

2.AST

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

AST的節(jié)點(diǎn)分為多種類型,對(duì)應(yīng)著PHP語法。

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

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

3.opcodes

opcode只是單條指令,opcodes是opcode的集合形式,是PHP執(zhí)行過程中的中間代碼。opcode生成之后由虛擬機(jī)執(zhí)行。

PHP工程優(yōu)化措施中有一個(gè)比較常見的“開啟opcache”,指的就是這里的opcodes的緩存(opcodes cache)。通過省去從源碼到opcode的階段,引擎可以直接執(zhí)行緩存的opcode,以此

提升性能。

借助vld插件,可以直觀地看到一段PHP代碼生成的opcode。

opcode是PHP 7定義的一組指令標(biāo)識(shí),指令對(duì)應(yīng)著相應(yīng)的handler(處理函數(shù))。當(dāng)虛擬機(jī)調(diào)用opcode,會(huì)找到opcode背后的處理函數(shù),執(zhí)行真正的處理。

二、內(nèi)核架構(gòu)

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

Zend引擎除了實(shí)現(xiàn)了PHP的核心功能,還提供了一套接口,讓PHP可以在更多的場(chǎng)景中使用,如命令行環(huán)境、Web環(huán)境等。

PHP7 源碼整體框架的示例分析

該架構(gòu)圖大致分為四大部分。

1)Zend引擎:前文介紹的詞法/語法分析、AST編譯和opcodes的執(zhí)行均在Zend引擎中實(shí)現(xiàn)。此外,PHP的變量設(shè)計(jì)、內(nèi)存管理、進(jìn)程管理等也在引擎層實(shí)現(xiàn)。引擎為PHP提供了基礎(chǔ)服務(wù),PHP的可靠性和高性能都依賴引擎的基礎(chǔ)支撐。同時(shí),Zend引擎的可擴(kuò)展性,還是PHP得以大規(guī)模應(yīng)用的重要原因之一。

2)PHP層:Zend引擎為PHP提供基礎(chǔ)能力(如內(nèi)存分配和回收),而來自外部的交互則需要通過PHP層來處理。

3)SAPI:SAPI是Server API的縮寫,其中包含了常見的cli SAPI和fpm SAPI。PHP定義好輸入/輸出規(guī)范,依據(jù)此規(guī)范與PHP交互的一方都可以稱為Server。

4)擴(kuò)展部分:Zend引擎提供了核心能力和接口規(guī)范。在此基礎(chǔ)上開發(fā)的擴(kuò)展,為PHP代碼的性能和功能的多樣性提供了更豐富的選項(xiàng)。

三、PHP源碼目錄

sapi目錄源碼

sapi目錄是對(duì)輸入和輸出層的抽象,是PHP提供對(duì)外服務(wù)的規(guī)范。

PHP程序的輸入可以是來自于命令行的標(biāo)準(zhǔn)輸入,也可以是來自基于cgi/fastcgi協(xié)議的網(wǎng)絡(luò)請(qǐng)求。同理,輸出可以寫到命令行的標(biāo)準(zhǔn)輸出,也可以作為基于cgi/fastcgi協(xié)議的網(wǎng)絡(luò)響應(yīng)返回給客戶端。

命令行模式對(duì)應(yīng)的是二進(jìn)制程序bin/php;內(nèi)置模塊的模式不需要提供二進(jìn)制程序,作為普通函數(shù)供Apache或任意C/C++程序來調(diào)用即可;CGI模式對(duì)應(yīng)的是二進(jìn)制程序bin/cgi;FastCGI模式對(duì)應(yīng)的是二進(jìn)制程序sbin/php-fpm。

幾種常用的SAPI。

1)apache2handler:Apache擴(kuò)展,編譯后生成動(dòng)態(tài)鏈接庫(kù),配置到Apache下,當(dāng)有http請(qǐng)求到Apache時(shí),根據(jù)配置會(huì)調(diào)用此動(dòng)態(tài)鏈接庫(kù),執(zhí)行PHP代碼,完成與PHP的交互。

2)cgi-fcgi:編譯后生成支持CGI協(xié)議的可執(zhí)行程序,webserver(通常為Apache或Nginx)通過CGI協(xié)議把請(qǐng)求傳給CGI進(jìn)程,執(zhí)行代碼將結(jié)果返回給webserver,退出進(jìn)程。

3)fpm-fcgi:fpm全稱為FastCGI Process Manager,PHP官方提供的FastCGI進(jìn)程管理器。以Nginx服務(wù)器為例,當(dāng)有http協(xié)議請(qǐng)求發(fā)送到Nginx服務(wù)器,Nginx按照FastCGI協(xié)議把請(qǐng)求交給php-fpm進(jìn)程處理。

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

Zend目錄源碼

Zend目錄是PHP的核心代碼。

1.內(nèi)存管理模塊

2.垃圾回收

3.數(shù)組實(shí)現(xiàn)

main目錄源碼

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

Zend層實(shí)現(xiàn)了PHP腳本的編譯和執(zhí)行,sapi層實(shí)現(xiàn)了輸入和輸出的抽象,main目錄則起到了承上啟下的作用:承上,解析SAPI的請(qǐng)求,分析要執(zhí)行的腳本文件和參數(shù);啟下,調(diào)用Zend引擎之前,完成必要的初始化等工作。

ext目錄源碼

ext是PHP擴(kuò)展相關(guān)的目錄,常用的array、str、pdo等系列函數(shù)都在這里定義。

TSRM目錄源碼

PHP在早期更多的是單個(gè)進(jìn)程、單線程模型運(yùn)行的,在后期才引入了線程安全機(jī)制ZTS(Zend Thread Safety)。

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

線程安全機(jī)制主要為了保證共享資源的安全。PHP的線程安全機(jī)制簡(jiǎn)潔直觀——在多線程環(huán)境下,為每個(gè)線程提供獨(dú)立的全局變量副本。具體實(shí)施是通過TSRM為每個(gè)線程分配(分配前加鎖)一個(gè)獨(dú)立ID(自增)作為當(dāng)前線程的全局變量?jī)?nèi)存區(qū)索引,在以后的全局變量訪問中,實(shí)現(xiàn)線程之間的完全獨(dú)立。

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“PHP7 源碼整體框架的示例分析”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI