web-dev-qa-db-fra.com

Où est le point d'entrée principal de php-src / PHP-Internals

Quelle fonction ou bit de code sert de point d'entrée principal pour exécuter/interpréter un programme PHP dans le source de PHP lui-même ? Sur la base de choses que j'ai googlé ou lu dans des livres, je sais que PHP est conçu pour fonctionner avec un serveur quelconque (même la commande CLI fonctionne en démarrant "la ligne de commande SAPI ", qui agit comme un mini-serveur conçu pour traiter une seule requête), et que le serveur demandera PHP pour exécuter un programme.

Je connais les fonctions de cycle de vie minit et rinit, qui servent de points d'entrée pour une extension PHP .

Ce que je ne sais pas, c'est où le code source PHP a-t-il cette conversation avec lui-même

Hé, regardez, il y a un programme PHP dans ce fichier/chaîne. Je devrais l'exécuter

Je n'essaie pas d'accomplir une tâche spécifique ici. J'essaie de comprendre comment les internes de PHP fait ce qu'il fait, et de trouver un point d'entrée principal où je peux commencer à suivre son exécution.

28
Alan Storm

Où est le point d'entrée du code de certains SAPI?

Le [~ # ~] cli [~ # ~] est une application autonome. Comme toute autre application écrite en C, son point d'entrée est la fonction main() (fichier sapi/cli/php_cli.c , ligne 1200 =):

int main(int argc, char *argv[])

Il existe deux versions de l'interface CLI pour Windows, l'une est une application console et démarre avec la fonction main() décrite ci-dessus, l'autre est une application graphique Windows (elle ne crée pas de console au démarrage) et utilise des boîtes de message pour la sortie) qui commence par la fonction WinMain() (fichier sapi/cli/php_cli.c , ligne 1198 ) .
main() et WinMain() utilisent le même code ici. Ils ont des noms et des fragments de code différents ici et là en vérifiant si le symbole PHP_CLI_WIN32_NO_CONSOLE Est défini. Il est défini dans le fichier sapi/cli/cli_win32.c qui est utilisé pour générer l'application GUI Windows.
</Windows>

La version [~ # ~] cgi [~ # ~] est également une application console autonome. Son point d'entrée est également la fonction main() dans le fichier sapi/cgi/cgi_main.c , ligne 1792 .

De même, la version [~ # ~] fpm [~ # ~] commence par main() dans le fichier sapi/fpm/fpm/fpm_main.c , ligne 1570 .

Le gestionnaire Apache2 est un module chargeable dynamiquement (.dll Sous Windows, .so Sur les systèmes de type Unix). Il enregistre certaines fonctions en tant que gestionnaires d'événements pour les événements publiés par le serveur Web (démarrage du serveur, configuration pré/post chargée, demande de processus, etc.). Ces gestionnaires sont enregistrés par la fonction php_ap2_register_hook() dans le fichier sapi/Apache2handler/sapi_Apache2.c , ligne 738 .
(Vous pouvez trouver des détails sur la façon dont un module chargeable s'intègre avec Apache dans la documentation Apache.)

Le gestionnaire qui nous intéresse est la fonction php_handler() qui est invoquée pour gérer une requête HTTP.

De la même manière, chaque SAPI a un point d'entrée (soit main() ou une fonction qui est invoquée par le serveur Web).

Tous ces points d'entrée effectuent un traitement similaire:

  • s'initialiser;
  • analyser les arguments de la ligne de commande (uniquement si c'est [~ # ~] cli [~ # ~] , [~ # ~] cgi [~ # ~] ou tout autre type d'application autonome);
  • lire php.ini et/ou toute autre configuration dont ils disposent (la configuration du module Apache peut être remplacée dans .htaccess);
  • créer un flux à l'aide du fichier d'entrée et le transmettre à la fonction php_execute_script() définie dans le fichier main/main.c , ligne 2496 ;
  • nettoyer et renvoyer un code de sortie au processus appelant (le Shell ou le serveur Web).

Où est le code qui exécute réellement un script PHP?

La fonction php_execute_script() est un wrapper; il interprète les entrées de configuration php.iniauto_prepend_file et auto_append_file , prépare la liste des fichiers (fichier à pré-ajout automatique, script principal, fichier auto-ajouté) et passe la liste à zend_execute_scripts() qui les traite.

php_execute_script() n'est pas toujours invoqué, certains SAPI et arguments de ligne de commande de la CLI produisent l'appel direct de zend_execute_scripts().

zend_execute_scripts() est l'endroit où les choses intéressantes se produisent.

Il compile le PHP (et retourne une liste de codes OP dans op_array Puis, si la compilation réussit ( le op_array retourné n'est pas NULL) il exécute les codes OP. Il y a aussi la gestion des exceptions et le nettoyage; travail ennuyeux mais aussi important que l'analyse et les exécutions néanmoins .

La compilation est un processus fastidieux. Cela se fait par la fonction zendparse() définie dans le fichier Zend/zend_language_parser.c. La définition de la fonction zendparse() et le fichier Zend/zend_language_parser.c Sont introuvables dans le dépôt Git; l'analyseur est généré à l'aide de bison et re2c qui lisent les règles de syntaxe du langage et la définition des jetons lexicaux de Zend/zend_language_parser.y et Zend/zend_language_scanner.l et générez le compilateur réel dans le fichier Zend/zend_language_parser.c.

Cependant, même si le travail acharné n'est pas visible dans le dépôt, les parties intéressantes du processus de compilation sont visibles dans les fichiers mentionnés ci-dessus.

L'exécution du script compilé (la liste des codes OP) se fait par la fonction zend_execute() définie dans le fichier Zend/zend_vm_execute.h . C'est aussi un fichier généré et la partie intéressante est qu'il est généré par un script PHP.

Le script générateur ( Zend/zend_vm_gen.php ) utilise zend_vm_def.h et zend_vm_execute.skl pour générer - zend_vm_execute.h et zend_vm_opcodes.h .

zend_vm_def.h contient le code d'interprétation réel qui est exécuté pour gérer chaque code OP.

Où est le code d'une fonction fournie par le noyau PHP ou l'une de ses extensions groupées?

Le code des fonctions PHP et des fonctions fournies par les extensions est en quelque sorte plus facile à suivre. Les fonctions incluses dans le noyau PHP sont situées dans des fichiers dans le - ext/standard répertoire, les fonctions fournies par d'autres extensions sont situées dans des fichiers dans les sous-répertoires correspondants ext .

Dans ces fichiers, les fonctions C qui implémentent PHP sont déclarées à l'aide de la macro PHP_FUNCTION(). Par exemple, l'implémentation de la PHP fonction strpos() commence dans le fichier ext/standard/string.c , ligne 1948 . La fonction - strchr() étant un alias de strstr() est déclaré à l'aide de la macro PHP_FALIAS() dans le fichier ext/standard/basic_functions.c en ligne 2833 .

Et ainsi de suite.

50
axiac