octobercms 执行php代码_PHP7语言执行原理
常用的高級(jí)語(yǔ)言有很多種,根據(jù)運(yùn)行的方式不同,大體分為兩種:編譯型語(yǔ)言和解釋型語(yǔ)言。
編譯是指在應(yīng)用源程序執(zhí)行之前,就將程序源代碼“翻譯”成匯編語(yǔ)言,然后進(jìn)一步根據(jù)軟硬件環(huán)境編譯成目標(biāo)文件。一般稱(chēng)完成編譯工作的工具為編譯器。
而解釋型語(yǔ)言,在程序運(yùn)行時(shí)才被“翻譯”為機(jī)器語(yǔ)言。但是執(zhí)行一次“翻譯”一次,所以執(zhí)行效率較低。解釋器的工作就是解釋型語(yǔ)言中,負(fù)責(zé)“翻譯”源代碼的程序。
對(duì)于一段C語(yǔ)言代碼,需要經(jīng)過(guò)預(yù)編譯、編譯、匯編和鏈接,才能成為可執(zhí)行的二進(jìn)制文件。
以C語(yǔ)言為代表的編譯型語(yǔ)言,代碼發(fā)生更新都要經(jīng)過(guò)以上步驟。
編譯型語(yǔ)言的執(zhí)行示意:
對(duì)編譯型語(yǔ)言與解釋型語(yǔ)言的區(qū)別的理解,立足于源代碼被編譯成目標(biāo)平臺(tái)CPU指令的時(shí)機(jī)。對(duì)于編譯型語(yǔ)言,編譯結(jié)果已經(jīng)是針對(duì)當(dāng)前CPU體系的指令;而解釋型語(yǔ)言,需要先編譯成中間代碼,再經(jīng)由該解釋型語(yǔ)言的特定虛擬機(jī),翻譯成特定CPU體系的指令被執(zhí)行。解釋型語(yǔ)言是在運(yùn)行過(guò)程中,翻譯為目標(biāo)平臺(tái)的指令。常說(shuō)解釋型語(yǔ)言“慢”,主要也是慢在這里。
在PHP 7中,源代碼首先進(jìn)行詞法分析,將源代碼切割為多個(gè)字符串單元,分割后的字符串稱(chēng)為T(mén)oken。而一個(gè)一個(gè)獨(dú)立的Token是無(wú)法表達(dá)完整語(yǔ)義的,需經(jīng)過(guò)語(yǔ)法分析階段,將Token轉(zhuǎn)換為抽象語(yǔ)法樹(shù)(簡(jiǎn)稱(chēng)AST)。之后,抽象語(yǔ)法樹(shù)被轉(zhuǎn)換為機(jī)器指令執(zhí)行。在PHP中,這些指令稱(chēng)為opcode。
第1步:源碼通過(guò)詞法分析得到Token。
第2步:基于語(yǔ)法分析器生成抽象語(yǔ)法樹(shù)(AST)。
第3步:抽象語(yǔ)法樹(shù)轉(zhuǎn)換為opcodes(opcode指令集合),PHP解釋執(zhí)行opcodes。
1.Token
Token是PHP代碼被切割成的有意義的標(biāo)識(shí)。PHP提供了token_get_all()函數(shù)來(lái)獲取PHP代碼被切割后的Token.。
二維數(shù)組的每個(gè)成員數(shù)組的第一個(gè)值為T(mén)oken對(duì)應(yīng)的枚舉值。第二個(gè)值為T(mén)oken對(duì)應(yīng)的原始字符串內(nèi)容。第三個(gè)值為代碼對(duì)應(yīng)的行號(hào)。
可見(jiàn),Token就是一個(gè)個(gè)的“詞塊”,但是單獨(dú)存在的詞塊不能表達(dá)完整的語(yǔ)義,還需要借助規(guī)則進(jìn)行組織串聯(lián)。語(yǔ)法分析器就是這個(gè)組織者。它會(huì)檢查語(yǔ)法,匹配Token,對(duì)Token進(jìn)行關(guān)聯(lián)。
2.AST
AST是PHP 7版本新特性。在這之前的版本中,PHP代碼的執(zhí)行過(guò)程中是沒(méi)有生成AST這一步的。
AST的節(jié)點(diǎn)分為多種類(lèi)型,對(duì)應(yīng)著PHP語(yǔ)法。
PHP-Parser工具,它可以用來(lái)查看PHP代碼生成的AST。
注意 PHP-Parser是PHP 7內(nèi)核作者之一Nikic編寫(xiě)的將PHP源碼生成AST的工具。源碼見(jiàn)https://github.com/nikic/PHP-Parser。
3.opcodes
opcode只是單條指令,opcodes是opcode的集合形式,是PHP執(zhí)行過(guò)程中的中間代碼。opcode生成之后由虛擬機(jī)執(zhí)行。
PHP工程優(yōu)化措施中有一個(gè)比較常見(jiàn)的“開(kāi)啟opcache”,指的就是這里的opcodes的緩存(opcodes cache)。通過(guò)省去從源碼到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)境等。
該架構(gòu)圖大致分為四大部分。
1)Zend引擎:前文介紹的詞法/語(yǔ)法分析、AST編譯和opcodes的執(zhí)行均在Zend引擎中實(shí)現(xiàn)。此外,PHP的變量設(shè)計(jì)、內(nèi)存管理、進(jìn)程管理等也在引擎層實(shí)現(xiàn)。引擎為PHP提供了基礎(chǔ)服務(wù),PHP的可靠性和高性能都依賴(lài)引擎的基礎(chǔ)支撐。同時(shí),Zend引擎的可擴(kuò)展性,還是PHP得以大規(guī)模應(yīng)用的重要原因之一。
2)PHP層:Zend引擎為PHP提供基礎(chǔ)能力(如內(nèi)存分配和回收),而來(lái)自外部的交互則需要通過(guò)PHP層來(lái)處理。
3)SAPI:SAPI是Server API的縮寫(xiě),其中包含了常見(jiàn)的cli SAPI和fpm SAPI。PHP定義好輸入/輸出規(guī)范,依據(jù)此規(guī)范與PHP交互的一方都可以稱(chēng)為Server。
4)擴(kuò)展部分:Zend引擎提供了核心能力和接口規(guī)范。在此基礎(chǔ)上開(kāi)發(fā)的擴(kuò)展,為PHP代碼的性能和功能的多樣性提供了更豐富的選項(xiàng)。三、PHP源碼目錄sapi目錄源碼
sapi目錄是對(duì)輸入和輸出層的抽象,是PHP提供對(duì)外服務(wù)的規(guī)范。
PHP程序的輸入可以是來(lái)自于命令行的標(biāo)準(zhǔn)輸入,也可以是來(lái)自基于cgi/fastcgi協(xié)議的網(wǎng)絡(luò)請(qǐng)求。同理,輸出可以寫(xiě)到命令行的標(biāo)準(zhǔn)輸出,也可以作為基于cgi/fastcgi協(xié)議的網(wǎng)絡(luò)響應(yīng)返回給客戶(hù)端。
命令行模式對(duì)應(yīng)的是二進(jìn)制程序bin/php;內(nèi)置模塊的模式不需要提供二進(jìn)制程序,作為普通函數(shù)供Apache或任意C/C++程序來(lái)調(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)通過(guò)CGI協(xié)議把請(qǐng)求傳給CGI進(jìn)程,執(zhí)行代碼將結(jié)果返回給webserver,退出進(jìn)程。
3)fpm-fcgi:fpm全稱(chēng)為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)稱(chēng),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的縮寫(xiě)——線程安全資源管理器。
線程安全機(jī)制主要為了保證共享資源的安全。PHP的線程安全機(jī)制簡(jiǎn)潔直觀——在多線程環(huán)境下,為每個(gè)線程提供獨(dú)立的全局變量副本。具體實(shí)施是通過(guò)TSRM為每個(gè)線程分配(分配前加鎖)一個(gè)獨(dú)立ID(自增)作為當(dāng)前線程的全局變量?jī)?nèi)存區(qū)索引,在以后的全局變量訪問(wèn)中,實(shí)現(xiàn)線程之間的完全獨(dú)立。
總結(jié)
以上是生活随笔為你收集整理的octobercms 执行php代码_PHP7语言执行原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python分析工具有哪些_常用Pyth
- 下一篇: php 其他页面获取session_PH