首頁 後端開發 php教程 PHP7語言的執行原理(PHP7源碼分析)

PHP7語言的執行原理(PHP7源碼分析)

Mar 20, 2019 am 11:04 AM

PHP7語言的執行原理(PHP7源碼分析)

我們常用的高階語言有很多種,比較出名的有CC 、Python、 PHP、Go、Pascal等。而這些語言依運行的方式不同,大體分為兩種:編譯型語言和解釋型語言。

其中,編譯型語言包括CC 、Pascal、Go等。這裡說的編譯是指在應用程式原始程式執行之前,就將程式原始碼「翻譯」成組合語言,然後進一步根據軟硬體環境編譯成目標檔。一般我們稱完成編譯工作的工具叫編譯器。而解釋型語言,在程式執行時才被「翻譯」為機器語言。但是執行一次「翻譯」一次,所以執行效率較低。解釋器的工作就是解釋性語言中,負責「翻譯」原始碼的程式。

下面我們更詳細地討論一下編譯型語言和解釋性語言的運作方式。

一、編譯型語言與解釋型語言

我們知道,對於一段C語言程式碼,需要經過預編譯、編譯、彙編和鏈接,才能成為可執行的二進位。以hello.c為例:

#include<stdio.h>
int main(){   
    printf("hello world");   
    return 1;
}
登入後複製

對於這段C程式碼,main是程式入口函數,實作的功能是列印字串「hello world」 到螢幕上。編譯與執行過程如圖1所示。

PHP7語言的執行原理(PHP7源碼分析)

圖1 編譯型語言的執行示意圖

第1步:C語言程式碼預處理(例如依賴處理、宏替換等)。如以上程式碼範例,#inlcude就會在預處理階段被取代。

第2步:編譯。編譯器會把C語言翻譯成組合語言程序,一條C語言通常便以為多條彙編程式碼。同時編譯器會對程式進行最佳化,產生目標組譯程式。

第3步:編譯得到的組譯語言透過組譯器再彙編成目標程式hello.o。

第4步:連結。程式中往往包含一些共享目標文件,如範例程式中的printf()函數,位於靜態庫,需要經過連結器(如Uinx連接器ld)進行連結。

以C語言為代表的編譯型語言,程式碼發生更新都要經過以上步驟:

我們區別編譯型語言與解釋型語言,主要立足於原始碼被編譯成目標平台CPU指令的時機。對於編譯型語言,編譯結果已經是針對目前CPU體系的指令;而解釋型語言,需要先編譯成中間碼,再經由該解釋型語言的特定虛擬機,翻譯成特定CPU體系的指令被執行。解釋型語言是在運作過程中,翻譯為目標平台的指令。常說解釋型語言“慢”,主要也是慢在這裡。

在PHP7中,原始碼首先將進行詞法分析,將原始碼切割為多個字串單元,分割後的字串稱為Token。而一個獨立的Token無法表達完整語意,需經過語法分析階段,將Token轉換為抽象語法樹(簡稱AST)。之後,抽象語法樹被轉換為機器指令執行。在PHP中,這些指令稱為opcode(後文會對opcode做更詳細的解釋,此處讀者可以看待為CPU指令)。

到AST的生成這一步,編譯型語言與解釋型語言所需經歷的過程相似。從抽象語法樹之後開始產生差異。

圖2是PHP(如無特殊說明,本章提到的PHP均為PHP7版本)程式碼被執行的簡化步驟,其中最後一步的左側分支,是編譯型語言的過程。

PHP7語言的執行原理(PHP7源碼分析)

圖2 以PHP為例解釋型語言的執行示意圖

第1步:原始碼透過詞法分析得到Token;

第2步:基於語法分析器產生抽象語法樹(AST);

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

接下來我們在基本步驟的基礎上,細化PHP語言的執行原理,試著更清楚地建立認知。

二、PHP7的執行原理概述

首先我們補充說明下前文提到的PHP7程式執行過程,請參考圖3。

PHP7語言的執行原理(PHP7源碼分析)

圖3 PHP7語言所寫的程式的執行過程圖

#第1步:詞法分析將PHP程式碼轉換為有意義的標識Token。該步驟的詞法分析器使用Re2c實現的。

第2步:语法分析将Token和符合文法规则的代码生成抽象语法树。语法分析器基于Bison实现。语法分析使用了巴科斯范式(BNF)来表达文法规则,Bison借助状态机、状态转移表和压栈、出栈等一系列操作,生成抽象语法树。

第3步:上步的抽象语法树生成对应的opcode,被虚拟机执行。opcode是PHP7定义的一组指令标识,指令对应着相应的handler(处理函数)。当虚拟机调用opcode,会找到opcode背后的处理函数,执行真正的处理。以我们常见的echo语句为例,其对应的opcode便是ZEND_ECHO。

注意:这里为了便于理解词法分析和语法分析过程,将两者分开描述。但实际情况,出于效率考虑,两个过程并非完全独立。

下面,我们通过一段示例代码,来建立PHP7运转的初步理解。

示例代码如下:

<?phpecho "hello world";
登入後複製

从图3可知,这段代码首先会被切割为Token。

1. Token

Token是PHP代码被切割成的有意义的标识。本书介绍的PHP7版本中有137 种Token,在zend_language_parser.h文件中做了定义:

/* Tokens.  */#define END 0#define T_INCLUDE 258#define T_INCLUDE_ONCE 259…#define T_ERROR 392
登入後複製

更多Token的含义,感兴趣的读者可以参考《PHP 7底层设计与源码实现》附录。

PHP提供了token_get_all()函数来获取PHP代码被切割后的Token,可以在深入源码学习前,粗略查看PHP代码被切割后的Token。如下代码片段:

/home/vagrant/php7/bin/php –r &#39;print_r(Token_get_all("<?php echo \"hello world\";"));&#39;
登入後複製

输出结果为:

Array
(
   [0] => Array
       (
           [0] => 379
           [1] => <?php
           [2] => 1
       )
   [1] => Array
       (
           [0] => 328
           [1] => echo
           [2] => 1
       )
   [2] => Array
       (
           [0] => 382
           [1] =>
           [2] => 1
       )
   [3] => Array
       (
           [0] => 323
           [1] => "hello world"
           [2] => 1
       )
   [4] => ;
)
登入後複製

上文输出中,二维数组的每个成员数组第一个值为Token对应的枚举值;第二个值为Token对应的原始字符串内容;第三个值为代码对应的行号。可以看出,词法解析器将

1)文本“

#dfine T_OPEN_TAG 379
登入後複製

不难理解,它是PHP代码的起始tag,也就是

2)echo对应的Token是T_ECHO:

#define T_ECHO 328
登入後複製

3)源码中的空格,对应的Token叫T_WHITESPACE,值为382:

#define T_WHITESPACE 382
登入後複製

4)字符串“hello world”对应的Token值为323:

#define T_CONSTANT_ENCAPSED_STRING 323
登入後複製

可见,Token就是一个个的“词块”,但是单独存在的词块不能表达完整的语义,还需要借助规则进行组织串联。语法分析器就是这个组织者。它会检查语法、匹配Token,对Token进行关联。

PHP7中,组织串联的产物就是抽象语法树(Abstract Syntax Tree,AST)。

2. AST

AST是PHP7版本新特性。在这之前的版本,PHP代码的执行过程中没有生成AST这一步。PHP7对抽象语法树的支持,实现了PHP编译器和解释器解耦,有效提升了可维护性。

顾名思义,抽象语法树具有树状结构。AST的节点分为多种类型,对应着不同的PHP语法。在当前章节,我们可以认为节点类型是对语法规则的抽象,例如赋值语句,生成的抽象语法树节点为ZEND_AST_ASSIGN。而赋值语句的左右操作数,又将作为ZEND_AST_ASSIGN类型节点的孩子。通过这样的节点关系,构建出抽象语法树。

如果读者希望一睹为快,可以直接跳到本书第13章函数的实现,其中图片描绘了一段简单的PHP代码生成的抽象语法树。

在这里,我们推荐读者了解下PhpParser工具,可以用它来查看PHP代码生成的AST。

注意:PHP-Parser是PHP7内核作者之一nikic编写的将PHP源码生成AST的工具。源码见https://github.com/nikic/PHP-...

3. Opcodes

AST扮演了源码到中间代码的临时存储介质的角色,还需要将其转换为opcode,才能被引擎直接执行。Opcode只是单条指令,Opcodes是opcode的集合形式,是PHP执行过程中的中间代码,类似Java中的字节码。生成之后由虚拟机执行。

我们知道,PHP工程优化措施中有个比较常见的“开启Opcache”,指的就是这里的Opcodes的缓存(Opcodes Cache)。通过省去从源码到opcode的阶段,引擎可以直接执行缓存的opcode,以此提升性能。

借助vld插件,可以直观地看到一段PHP代码生成的opcode:

php -dvld.active=1 hello.php
登入後複製

经过过滤整理,对应的opcode为:

line     op              
 1      ECHO            
 2      RETURN
登入後複製

其实在源码实现中,上述代码生成的opcode及handler为:

ZEND_ECHO  // handler: ZEND_ECHO_SPEC_CONST_HANDLERZEND_RETURN  // handler: ZEND_RETURN_SPEC_CONST_HANDLER
登入後複製

可见,ZEND_ECHO对应的handler是ZEND_ECHO_SPEC_CONST_HANDLER。此handler的实现的功能便是预期的“hello world”语句的输出。

相关推荐:《PHP7新特性手册

以上是PHP7語言的執行原理(PHP7源碼分析)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1666
14
CakePHP 教程
1425
52
Laravel 教程
1325
25
PHP教程
1272
29
C# 教程
1252
24
說明PHP中的安全密碼散列(例如,password_hash,password_verify)。為什麼不使用MD5或SHA1? 說明PHP中的安全密碼散列(例如,password_hash,password_verify)。為什麼不使用MD5或SHA1? Apr 17, 2025 am 12:06 AM

在PHP中,應使用password_hash和password_verify函數實現安全的密碼哈希處理,不應使用MD5或SHA1。1)password_hash生成包含鹽值的哈希,增強安全性。 2)password_verify驗證密碼,通過比較哈希值確保安全。 3)MD5和SHA1易受攻擊且缺乏鹽值,不適合現代密碼安全。

PHP和Python:比較兩種流行的編程語言 PHP和Python:比較兩種流行的編程語言 Apr 14, 2025 am 12:13 AM

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

PHP行動:現實世界中的示例和應用程序 PHP行動:現實世界中的示例和應用程序 Apr 14, 2025 am 12:19 AM

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

PHP:網絡開發的關鍵語言 PHP:網絡開發的關鍵語言 Apr 13, 2025 am 12:08 AM

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

PHP類型提示如何起作用,包括標量類型,返回類型,聯合類型和無效類型? PHP類型提示如何起作用,包括標量類型,返回類型,聯合類型和無效類型? Apr 17, 2025 am 12:25 AM

PHP類型提示提升代碼質量和可讀性。 1)標量類型提示:自PHP7.0起,允許在函數參數中指定基本數據類型,如int、float等。 2)返回類型提示:確保函數返回值類型的一致性。 3)聯合類型提示:自PHP8.0起,允許在函數參數或返回值中指定多個類型。 4)可空類型提示:允許包含null值,處理可能返回空值的函數。

PHP的持久相關性:它還活著嗎? PHP的持久相關性:它還活著嗎? Apr 14, 2025 am 12:12 AM

PHP仍然具有活力,其在現代編程領域中依然佔據重要地位。 1)PHP的簡單易學和強大社區支持使其在Web開發中廣泛應用;2)其靈活性和穩定性使其在處理Web表單、數據庫操作和文件處理等方面表現出色;3)PHP不斷進化和優化,適用於初學者和經驗豐富的開發者。

PHP與其他語言:比較 PHP與其他語言:比較 Apr 13, 2025 am 12:19 AM

PHP適合web開發,特別是在快速開發和處理動態內容方面表現出色,但不擅長數據科學和企業級應用。與Python相比,PHP在web開發中更具優勢,但在數據科學領域不如Python;與Java相比,PHP在企業級應用中表現較差,但在web開發中更靈活;與JavaScript相比,PHP在後端開發中更簡潔,但在前端開發中不如JavaScript。

PHP和Python:代碼示例和比較 PHP和Python:代碼示例和比較 Apr 15, 2025 am 12:07 AM

PHP和Python各有優劣,選擇取決於項目需求和個人偏好。 1.PHP適合快速開發和維護大型Web應用。 2.Python在數據科學和機器學習領域佔據主導地位。

See all articles