Maison développement back-end tutoriel php Le principe d'exécution du langage PHP7 (analyse du code source PHP7)

Le principe d'exécution du langage PHP7 (analyse du code source PHP7)

Mar 20, 2019 am 11:04 AM

Le principe d'exécution du langage PHP7 (analyse du code source PHP7)

Il existe de nombreux langages de haut niveau que nous utilisons couramment, les plus connus incluent CC++, Python, PHP, Go, Pascal, etc. Ces langages peuvent être grossièrement divisés en deux types selon leur mode d'exécution : les langages compilés et les langages interprétés.

Parmi eux, les langages compilés incluent CC++, Pascal, Go, etc. La compilation mentionnée ici signifie qu'avant l'exécution du programme source de l'application, le code source du programme est « traduit » en langage assembleur, puis compilé dans un fichier cible en fonction de l'environnement logiciel et matériel. Généralement, nous appelons l’outil qui effectue le travail de compilation un compilateur. Les langages interprétés sont « traduits » en langage machine lors de l'exécution du programme. Cependant, la « traduction » est effectuée une seule fois, donc l'efficacité d'exécution est faible. Le travail de l'interprète est le programme chargé de « traduire » le code source dans un langage interprété.

Discutons plus en détail du fonctionnement des langages compilés et interprétés.

1. Langages compilés et langages interprétés

Nous savons qu'un morceau de code en langage C doit être précompilé, compilé, assemblé et lié avant lui. peut devenir lisible Fichier binaire exécuté. Prenons hello.c comme exemple :

#include<stdio.h>
int main(){   
    printf("hello world");   
    return 1;
}
Copier après la connexion

Pour ce code C, main est la fonction d'entrée du programme, et sa fonction est d'imprimer la chaîne "hello world" à l'écran. Le processus de compilation et d'exécution est illustré à la figure 1.

Le principe dexécution du langage PHP7 (analyse du code source PHP7)

Figure 1 Diagramme schématique de l'exécution du langage compilé

Étape 1 : Prétraitement du code du langage C (tel que le traitement des dépendances, le remplacement des macros , etc.). Comme dans l'exemple de code ci-dessus, #inlcude sera remplacé lors de l'étape de prétraitement.

Étape 2 : Compiler. Le compilateur traduira le langage C en un programme en langage assembleur. Un morceau de langage C représente généralement plusieurs lignes de code assembleur. Dans le même temps, le compilateur optimisera le programme et générera un programme assembleur cible.

Étape 3 : Le langage assembleur compilé est ensuite assemblé dans le programme cible hello.o via l'assembleur.

Étape 4 : Lien. Les programmes contiennent souvent des fichiers objets partagés, tels que la fonction printf() dans l'exemple de programme, qui se trouve dans une bibliothèque statique et doit être liée via un éditeur de liens (tel que le connecteur Uinx ld).

Dans les langages compilés représentés par le langage C, les mises à jour du code doivent passer par les étapes ci-dessus :

On distingue les langages compilés et les langages interprétés, principalement en fonction du code source en cours de compilation dans une cible Le timing des instructions CPU de la plate-forme. Pour les langages compilés, les résultats de la compilation sont déjà des instructions pour le système CPU actuel ; pour les langages interprétés, ils doivent d'abord être compilés en code intermédiaire, puis traduits en instructions pour un système CPU spécifique via la machine virtuelle spécifique du langage interprété pour exécution. Les langues interprétées sont traduites en instructions pour la plate-forme cible pendant l'exécution. On dit souvent que les langues interprétées sont « lentes », et c’est principalement pour cela qu’elles sont lentes.

En PHP7, le code source sera d'abord analysé lexicalement, et le code source sera découpé en plusieurs unités de chaînes. Les chaînes divisées sont appelées jetons. Chaque jeton indépendant ne peut pas exprimer une sémantique complète et doit passer par l’étape d’analyse syntaxique pour convertir le jeton en un arbre syntaxique abstrait (AST). Ensuite, l'arbre de syntaxe abstraite est converti en instructions machine pour exécution. En PHP, ces instructions sont appelées opcode (l'opcode sera expliqué plus en détail plus tard, et les lecteurs peuvent le considérer ici comme des instructions CPU).

Jusqu'à l'étape de génération d'AST, les langages compilés et les langages interprétés passent par un processus similaire. Les différences commencent après l’arbre syntaxique abstrait.

La figure 2 montre les étapes simplifiées dans lesquelles le code PHP (si aucune instruction spéciale n'est spécifiée, le PHP mentionné dans ce chapitre est la version PHP7) est exécuté. La branche gauche de la dernière étape est le processus de langage compilé. .

Le principe dexécution du langage PHP7 (analyse du code source PHP7)

Figure 2 En prenant PHP comme exemple de schéma d'exécution d'un langage interprété

Étape 1 : Le code source obtient le Jeton via analyse lexicale ;

Étape 2 : Générer un arbre de syntaxe abstraite (AST) basé sur l'analyseur de syntaxe

Étape 3 : Convertir la syntaxe abstraite ; arbre en Opcodes (jeu d'instructions opcode), PHP interprète et exécute les Opcodes.

Ensuite, sur la base des étapes de base, nous affinerons le principe d'exécution du langage PHP et tenterons d'en établir une compréhension plus claire.

2. Aperçu du principe d'exécution de PHP7

Tout d'abord, nous compléterons le processus d'exécution du programme PHP7 mentionné ci-dessus, veuillez voir la figure 3.

Le principe dexécution du langage PHP7 (analyse du code source PHP7)

Figure 3 Schéma du processus d'exécution d'un programme écrit en langage PHP7

Étape 1  : L'analyse lexicale convertit le code PHP en identification significative Jeton. L'analyseur lexical pour cette étape est implémenté à l'aide de Re2c.

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

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

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

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

示例代码如下:

<?phpecho "hello world";
Copier après la connexion

从图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
Copier après la connexion

更多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;
Copier après la connexion

输出结果为:

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] => ;
)
Copier après la connexion

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

1)文本“

#dfine T_OPEN_TAG 379
Copier après la connexion

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

2)echo对应的Token是T_ECHO:

#define T_ECHO 328
Copier après la connexion

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

#define T_WHITESPACE 382
Copier après la connexion

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

#define T_CONSTANT_ENCAPSED_STRING 323
Copier après la connexion

可见,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
Copier après la connexion

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

line     op              
 1      ECHO            
 2      RETURN
Copier après la connexion

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

ZEND_ECHO  // handler: ZEND_ECHO_SPEC_CONST_HANDLERZEND_RETURN  // handler: ZEND_RETURN_SPEC_CONST_HANDLER
Copier après la connexion

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

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

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
Will R.E.P.O. Vous avez un jeu croisé?
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Expliquez les jetons Web JSON (JWT) et leur cas d'utilisation dans les API PHP. Expliquez les jetons Web JSON (JWT) et leur cas d'utilisation dans les API PHP. Apr 05, 2025 am 12:04 AM

JWT est une norme ouverte basée sur JSON, utilisée pour transmettre en toute sécurité des informations entre les parties, principalement pour l'authentification de l'identité et l'échange d'informations. 1. JWT se compose de trois parties: en-tête, charge utile et signature. 2. Le principe de travail de JWT comprend trois étapes: la génération de JWT, la vérification de la charge utile JWT et l'analyse. 3. Lorsque vous utilisez JWT pour l'authentification en PHP, JWT peut être généré et vérifié, et les informations sur le rôle et l'autorisation des utilisateurs peuvent être incluses dans l'utilisation avancée. 4. Les erreurs courantes incluent une défaillance de vérification de signature, l'expiration des jetons et la charge utile surdimensionnée. Les compétences de débogage incluent l'utilisation des outils de débogage et de l'exploitation forestière. 5. L'optimisation des performances et les meilleures pratiques incluent l'utilisation des algorithmes de signature appropriés, la définition des périodes de validité raisonnablement,

Décrivez les principes solides et comment ils s'appliquent au développement de PHP. Décrivez les principes solides et comment ils s'appliquent au développement de PHP. Apr 03, 2025 am 12:04 AM

L'application du principe solide dans le développement de PHP comprend: 1. Principe de responsabilité unique (SRP): Chaque classe n'est responsable d'une seule fonction. 2. Principe ouvert et ferme (OCP): les changements sont réalisés par extension plutôt que par modification. 3. Principe de substitution de Lisch (LSP): les sous-classes peuvent remplacer les classes de base sans affecter la précision du programme. 4. Principe d'isolement d'interface (ISP): utilisez des interfaces à grain fin pour éviter les dépendances et les méthodes inutilisées. 5. Principe d'inversion de dépendance (DIP): les modules élevés et de bas niveau reposent sur l'abstraction et sont mis en œuvre par injection de dépendance.

Expliquez le concept de liaison statique tardive en PHP. Expliquez le concept de liaison statique tardive en PHP. Mar 21, 2025 pm 01:33 PM

L'article traite de la liaison statique tardive (LSB) dans PHP, introduite dans PHP 5.3, permettant une résolution d'exécution de la méthode statique nécessite un héritage plus flexible. Problème main: LSB vs polymorphisme traditionnel; Applications pratiques de LSB et perfo potentiel

Comment envoyer une demande post contenant des données JSON à l'aide de la bibliothèque Curl de PHP? Comment envoyer une demande post contenant des données JSON à l'aide de la bibliothèque Curl de PHP? Apr 01, 2025 pm 03:12 PM

Envoyant des données JSON à l'aide de la bibliothèque Curl de PHP dans le développement de PHP, il est souvent nécessaire d'interagir avec les API externes. L'une des façons courantes consiste à utiliser la bibliothèque Curl pour envoyer le post� ...

Caractéristiques de sécurité du cadre: protection contre les vulnérabilités. Caractéristiques de sécurité du cadre: protection contre les vulnérabilités. Mar 28, 2025 pm 05:11 PM

L'article traite des fonctionnalités de sécurité essentielles dans les cadres pour se protéger contre les vulnérabilités, notamment la validation des entrées, l'authentification et les mises à jour régulières.

Comment définir automatiquement les autorisations d'UnixSocket après le redémarrage du système? Comment définir automatiquement les autorisations d'UnixSocket après le redémarrage du système? Mar 31, 2025 pm 11:54 PM

Comment définir automatiquement les autorisations d'UnixSocket après le redémarrage du système. Chaque fois que le système redémarre, nous devons exécuter la commande suivante pour modifier les autorisations d'UnixSocket: sudo ...

Frameworks de personnalisation / d'extension: comment ajouter des fonctionnalités personnalisées. Frameworks de personnalisation / d'extension: comment ajouter des fonctionnalités personnalisées. Mar 28, 2025 pm 05:12 PM

L'article examine l'ajout de fonctionnalités personnalisées aux cadres, en se concentrant sur la compréhension de l'architecture, l'identification des points d'extension et les meilleures pratiques pour l'intégration et le débogage.

See all articles