Maison > Article > développement back-end > Une explication du mécanisme de fonctionnement sous-jacent et des principes de PHP
On dit que PHP est simple, mais il n'est pas facile de le maîtriser. En plus de pouvoir l’utiliser, nous devons également connaître son principe de fonctionnement sous-jacent.
PHP est un langage dynamique adapté au développement web. Pour être plus précis, il s'agit d'un framework logiciel qui utilise le langage C pour implémenter un grand nombre de composants. Dans un sens plus étroit, il peut être considéré comme un puissant cadre d’interface utilisateur.
Quel est le but de comprendre l’implémentation sous-jacente de PHP ? Pour bien utiliser le langage dynamique, nous devons d'abord le comprendre. La gestion de la mémoire et les modèles de framework sont dignes de notre référence, nous pouvons obtenir des fonctions plus puissantes et optimiser les performances de nos programmes.
Le concept de conception et les caractéristiques de PHP
Modèle multi-processus : PHP étant un modèle multi-processus, les différentes requêtes n'interfèrent pas les unes avec les autres, ce qui garantit cette requête ne raccrochera pas. Cela aura un impact sur l'ensemble du service. Bien entendu, avec l'évolution des temps, PHP a déjà pris en charge le modèle multi-thread.
Langage faiblement typé : contrairement à C/C++, Java, C# et d'autres langages, PHP est un langage faiblement typé. Le type d'une variable n'est pas déterminé au début. Il est déterminé lors du fonctionnement et une conversion de type implicite ou explicite peut se produire. La flexibilité de ce mécanisme est très pratique et efficace dans le développement Web. Les détails seront discutés plus tard dans les variables PHP. sont détaillés dans.
Le mode moteur (Zend) + composant (ext) réduit le couplage interne.
La couche intermédiaire (sapi) isole le serveur web et PHP.
La syntaxe est simple et flexible, sans trop de spécifications. Les lacunes conduisent à des styles mixtes, mais peu importe à quel point un programmeur est mauvais, il n'écrira pas un programme trop scandaleux et qui mettrait en danger la situation globale.
Le système à quatre couches de PHP
L'architecture de base de PHP est la suivante :
Comme vous peut le voir sur l'image, PHP est un système à 4 couches de bas en haut :
Moteur Zend : Zend est entièrement implémenté en C pur et est la partie centrale de PHP. Il traduit le code PHP (lexical, lexical. L'analyse syntaxique et d'autres processus de compilation) sont utilisés pour traiter les opcodes exécutables et implémenter les méthodes de traitement correspondantes, implémenter les structures de données de base (telles que la table de hachage, oo), l'allocation et la gestion de la mémoire et fournir les méthodes API correspondantes pour les appels externes. tout et tous les périphériques. Les fonctions sont toutes implémentées autour de Zend.
Extensions : centrées sur le moteur Zend, les extensions fournissent divers services de base basés sur des composants. Nos diverses fonctions intégrées communes (telles que les séries de tableaux), les bibliothèques standard, etc. sont toutes implémentées via des extensions. Utilisateurs également Vous pouvez implémenter votre propre extension selon vos besoins pour atteindre l'expansion des fonctions, l'optimisation des performances et à d'autres fins (par exemple, la couche intermédiaire PHP et l'analyse de texte enrichi actuellement utilisées par Tieba sont des applications d'extension typiques).
Sapi : Le nom complet de Sapi est Server Application Programming Interface, qui est l'interface de programmation d'applications serveur. Sapi permet à PHP d'interagir avec les données périphériques via une série de fonctions de hook. de PHP. Grâce à sapi, PHP lui-même est découplé et isolé avec succès des applications de couche supérieure. PHP ne peut plus réfléchir à la manière d'être compatible avec différentes applications, et l'application elle-même peut également implémenter différentes méthodes de traitement en fonction de ses propres caractéristiques.
Application de couche supérieure : il s'agit du programme PHP que nous écrivons habituellement. Nous obtenons différents modes d'application via différentes méthodes sapi, telles que l'implémentation d'applications Web via un serveur Web, leur exécution en mode script sur la ligne de commande, etc.
Si PHP est une voiture, alors le châssis de la voiture est PHP lui-même, Zend est le moteur de la voiture (moteur), les différents composants sous Ext sont les roues de la voiture, et Sapi peut être considéré en tant que route,
Les voitures peuvent rouler sur différents types de routes, et l'exécution d'un programme PHP signifie que la voiture roule sur la route. Il nous faut donc : un moteur performant + les bonnes roues + la bonne chenille.
3.Sapi
Comme mentionné ci-dessus, Sapi permet aux applications externes d'échanger des données avec PHP via une série d'interfaces et peut implémenter des fonctions spécifiques en fonction des caractéristiques de différents applications. Certaines de nos méthodes de traitement sapi courantes sont :
apache2handler : il s'agit de la méthode de traitement lors de l'utilisation d'Apache comme serveur Web et de l'exécution en mode mod_PHP. C'est également la méthode la plus utilisée actuellement.
cgi : Il s'agit d'une autre méthode d'interaction directe entre le serveur Web et PHP, qui est le célèbre protocole fastcgi Ces dernières années, fastcgi+PHP a été de plus en plus utilisé, et c'est aussi la seule méthode supportée par l'asynchrone. serveur Web.
cli : Mode d'application pour les appels en ligne de commande
4. Processus d'exécution et opcode de PHP
Jetons d'abord un coup d'œil au processus d'exécution de PHP. processus de codage.
Comme vous pouvez le voir sur l'image, PHP implémente un processus d'exécution de langage dynamique typique : après avoir obtenu un morceau de code , après l'analyse lexicale, l'analyse syntaxique et d'autres étapes, le programme source sera traduit en instructions
(opcodes) une par une, puis la machine virtuelle ZEND exécutera ces instructions dans l'ordre pour terminer l'opération. PHP lui-même est implémenté en C, donc les fonctions finalement appelées sont toutes des fonctions C. En fait, nous pouvons considérer PHP comme un logiciel développé en C.
Le cœur de l'exécution de PHP réside dans les instructions traduites, qui sont des opcodes.
L'Opcode est l'unité la plus basique de l'exécution d'un programme PHP. Un opcode se compose de deux paramètres (op1, op2), d'une valeur de retour et d'une fonction de traitement. Le programme PHP se traduit finalement par l'exécution séquentielle d'un ensemble de fonctions de traitement d'opcodes.
Plusieurs fonctions de traitement courantes :
ZEND_ASSIGN_SPEC_CV_CV_HANDLER : 变量分配 ($a=$b) ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER:函数调用 ZEND_CONCAT_SPEC_CV_CV_HANDLER:字符串拼接 $a.$b ZEND_ADD_SPEC_CV_CONST_HANDLER: 加法运算 $a+2 ZEND_IS_EQUAL_SPEC_CV_CONST:判断相等 $a==1 ZEND_IS_IDENTICAL_SPEC_CV_CONST:判断相等 $a===1
5.HashTable — structure de données de base
HashTable est la structure de données de base de PHP zend. utilisé pour implémenter presque toutes les fonctions courantes.Le tableau PHP que nous connaissons est son application typique. De plus, dans zend, les tables de symboles de fonction, les variables globales, etc. sont également implémentées sur la base de tables de hachage.
La table de hachage de PHP présente les fonctionnalités suivantes :
Prend en charge les requêtes clé>valeur typiques
Peut être utilisée comme un tableau
Ajouter et supprimer des nœuds sont une complexité O(1)
la clé prend en charge les types mixtes : le tableau d'index de combinaison de nombres associatif existe en même temps
La valeur prend en charge les types mixtes : tableau ("string", 2332)
Traversée linéaire prise en charge : par exemple, foreach
La table de hachage Zend implémente une structure de hachage de table de hachage typique et fournit en même temps la fonction de parcours avant et arrière du tableau en attachant une liste doublement chaînée. Sa structure est la suivante :
Comme vous pouvez le voir, il existe à la fois des structures de hachage sous forme de clé->valeur et un mode liste doublement chaînée dans la table de hachage, ce qui le rend très pratique pour la recherche rapide et le parcours linéaire.
Structure de hachage : la structure de hachage de Zend est un modèle de table de hachage typique, qui utilise une liste chaînée pour résoudre les conflits. Il convient de noter que la table de hachage de Zend est une structure de données à croissance automatique. Lorsque le nombre de tables de hachage est plein, elle s'étendra dynamiquement de 2 fois et repositionnera les éléments. La taille initiale est de 8. De plus, lors de l'exécution d'une recherche rapide clé->valeur, zend lui-même a également apporté quelques optimisations pour accélérer le processus en échangeant de l'espace contre du temps. Par exemple, une variable nKeyLength est utilisée dans chaque élément pour identifier la longueur de la clé pour une détermination rapide.
Liste chaînée double : la table de hachage Zend implémente un parcours linéaire d'éléments via une structure de liste chaînée. En théorie, il suffit d'utiliser une liste chaînée unidirectionnelle pour le parcours. L'objectif principal de l'utilisation d'une liste chaînée bidirectionnelle est de supprimer rapidement et d'éviter le parcours. La table de hachage Zend est une structure composite lorsqu'elle est utilisée comme tableau, elle prend en charge les tableaux associatifs communs et peut également être utilisée comme numéros d'index séquentiels, et permet même un mélange des deux.
Tableau associatif PHP : le tableau associatif est une application hash_table typique. Un processus de requête passe par les étapes suivantes (comme le montre le code, il s'agit d'un processus de requête de hachage courant et quelques jugements rapides sont ajoutés pour accélérer la recherche.) :
getKeyHashValue h; index = n & nTableMask; Bucket *p = arBucket[index]; while (p) { if ((p->h == h) && (p->nKeyLength == nKeyLength)) { RETURN p->data; } p=p->next; } RETURN FALTURE;
Tableau d'index PHP : Le tableau d'index est notre tableau commun de , accessible via un indice. Par exemple, $arr[0], Zend HashTable est normalisé en interne et la clé de type d'index se voit également attribuer une valeur de hachage et nKeyLength (0). La variable membre interne nNextFreeElement est l'identifiant maximum actuellement attribué, qui est automatiquement augmenté de un après chaque poussée. C'est ce processus de normalisation qui permet à PHP de réaliser un mélange de données associatives et non associatives. En raison de la particularité de l'opération push, l'ordre des clés d'index dans le tableau PHP n'est pas déterminé par la taille de l'indice, mais par l'ordre du push. Par exemple, $arr[1] = 2; $arr[2] = 3; pour les clés de type double, Zend HashTable les traitera comme des clés d'index
6. >PHP est un langage faiblement typé et ne distingue pas strictement les types de variables. PHP n'a pas besoin de spécifier le type lors de la déclaration des variables. PHP peut effectuer des conversions implicites de types de variables lors de l'exécution du programme. Comme d'autres langages fortement typés, une conversion de type explicite peut également être effectuée dans le programme. Les variables PHP peuvent être divisées en types simples (int, string, bool), types de collection (objet ressource tableau) et constantes (const). Toutes les variables ci-dessus ont la même structure zval sous le capot.
Zval est une autre structure de données très importante dans zend, utilisée pour identifier et implémenter les variables PHP. Sa structure de données est la suivante :
Zval est principalement composé. de trois Composition de partie :
La relation correspondante entre les types de variables PHP et leur stockage réel est la suivante :
Le comptage de références est largement utilisé dans le recyclage de la mémoire, les opérations sur les chaînes, etc. Les variables en PHP sont une application typique du comptage de références. Le comptage de références de Zval est implémenté via les variables membres is_ref et ref_count. Grâce au comptage de références, plusieurs variables peuvent partager les mêmes données. Évitez la consommation énorme causée par des copies fréquentes.IS_LONG -> lvalue IS_DOUBLE -> dvalue IS_ARRAY -> ht IS_STRING -> str IS_RESOURCE -> lvalue
Lors de l'exécution d'une opération d'affectation, zend pointe la variable vers les mêmes zval et ref_count++, et pendant l'opération de non-définition, le ref_count-1 correspondant. L'opération de destruction ne sera effectuée que lorsque ref_count sera réduit à 0. S'il s'agit d'une affectation de référence, zend modifiera is_ref à 1.
Les variables PHP réalisent le partage de données variables grâce au comptage de références. Et si vous modifiez la valeur de l'une des variables ? Lorsque vous essayez d'écrire une variable, si Zend constate que le zval pointé par la variable est partagé par plusieurs variables, il copiera un zval avec un ref_count de 1 et décrémentera le refcount du zval d'origine. Ce processus est appelé "séparation zval". ". On peut voir que ce n'est que lorsqu'une opération d'écriture se produit
zend effectuera l'opération de copie, on l'appelle donc également copie sur écriture (copie sur écriture)
Pour les variables de référence, son exigences et non-référence Au contraire, les variables affectées par référence doivent être regroupées. La modification d'une variable modifie toutes les variables regroupées.
Les nombres entiers et les nombres à virgule flottante sont l'un des types de base en PHP et sont également des variables simples. Pour les entiers et les nombres à virgule flottante, les valeurs correspondantes sont stockées directement dans zvalue. Leurs types sont respectivement longs et doubles.
Comme le montre la structure zvalue, pour les types entiers, contrairement aux langages fortement typés tels que c, PHP ne fait pas de distinction entre int, unsignedint, long, long
long et autres types Par exemple, il n’existe qu’un seul type d’entier, qui est long. De là, on peut voir qu'en PHP, la plage de valeurs des entiers est déterminée par le nombre de bits du compilateur et n'est pas fixe.
Pour les nombres à virgule flottante, similaires aux entiers, il ne fait pas de distinction entre float et double mais seulement double.
En PHP, que dois-je faire si la plage entière est hors limites ? Dans ce cas, il sera automatiquement converti en type double. Vous devez faire attention à cela, car cela provoque de nombreuses astuces.
Comme les entiers, les variables de caractères sont également des types de base et des variables simples en PHP. Il ressort de la structure zvalue qu'en PHP, une chaîne est composée d'un pointeur vers les données réelles et d'une structure de longueur
, qui est similaire à la chaîne en C++. Puisque la longueur est représentée par une variable réelle, contrairement à c, sa chaîne peut être une donnée binaire (y compris
Destruction des ressources : Les types de données des ressources sont divers. Zend lui-même n'a aucun moyen de le détruire. Par conséquent, les utilisateurs doivent fournir une fonction de destruction lors de l’enregistrement des ressources. Lorsque les ressources sont désactivées, zend appelle la fonction correspondante pour terminer la destruction. Supprimez-le également de la table des ressources globales.
Les ressources peuvent persister pendant une longue période, non seulement après que toutes les variables y faisant référence soient hors de portée, mais même après la fin d'une requête et la génération d'une nouvelle requête. Ces ressources sont appelées ressources persistantes car elles persistent tout au long du cycle de vie du SAPI, à moins qu'elles ne soient spécifiquement détruites. Dans de nombreux cas, les ressources persistantes peuvent améliorer les performances dans une certaine mesure. Par exemple, dans notre mysql_pconnect commun, les ressources persistantes allouent de la mémoire via pemalloc afin qu'elles ne soient pas libérées à la fin de la requête. Pour Zend, il n'y a pas de distinction entre les deux en soi.
Comment les variables locales et globales sont-elles implémentées en PHP ? Pour une requête, PHP peut voir deux tables de symboles (symbol_table et
active_symbol_table) à tout moment, la première étant utilisée pour gérer les variables globales. Ce dernier est un pointeur pointant vers la table de symboles variable actuellement active Lorsque le programme entre dans une fonction, zend
lui allouera une table de symboles x et pointera active_symbol_table vers a. De cette manière, la distinction entre les variables globales et locales est réalisée.
Obtenir les valeurs des variables : la table des symboles de PHP est implémentée via hash_table. Chaque variable se voit attribuer un identifiant unique lors de l'obtention, le zval correspondant est trouvé dans la table et renvoyé en fonction de l'identifiant.
Utiliser des variables globales dans les fonctions : Dans les fonctions, nous pouvons utiliser des variables globales en déclarant explicitement global. Créez une référence à la variable du même nom dans symbol_table dans active_symbol_table. S'il n'y a pas de variable du même nom dans symbol_table, elle sera créée en premier.
Articles connexes :
Interprétation approfondie du mécanisme de fonctionnement de PHP
Interprétation approfondie de PHP mécanisme de fonctionnement. Jetons un coup d'œil au processus du mécanisme d'exploitation PHP suivant : 1. Nous n'avons jamais démarré manuellement les processus liés à PHP, c'est avec l'Ap...
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!