Maison > développement back-end > tutoriel php > Introduction aux connaissances liées au développement de modules php

Introduction aux connaissances liées au développement de modules php

伊谢尔伦
Libérer: 2023-03-11 06:46:01
original
1877 Les gens l'ont consulté

Architecture du code PHP

Toutes les parties de PHP sont dans une couche appelée TSRM. La couche TSRM est responsable de la gestion de la sécurité du thread. comme la ligne de commande sapi est cli, php-fpm est le sapi de fastcgi, et le mode module d'apache est également un

noyau PHP et moteur Zend. opérations sur les fichiers, le noyau Zend est responsable de la compilation et de l'exécution/allocation de la mémoire et des ressources.

En plus de tout cela, il y a la couche d'extension. La plupart des interfaces externes en PHP sont fournies via la couche d'extension, comme. as, Les fondements du langage tels que standard et string sont également fournis sous forme d'extensions

Il existe deux façons de charger des extensions (ci-après appelées modules) dans PHP : la compilation statique, la liaison dynamique

.

Compilation statique Le script configure de PHP doit être régénéré, ce qui ne sera pas décrit ici. La méthode du lien dynamique consiste à compiler le module dans un fichier .so puis à le charger dynamiquement dans PHP

. Il existe deux façons de charger le fichier .so. L'une consiste à l'écrire dans le fichier php.ini, par exemple : extension=apc.so, l'autre consiste à utiliser dl('xxx.so').

dl($library)

est de charger un module pour rendre disponible ses capacités internes. Le code source de la fonction

dl() est dans le PHP. répertoire racine du code source (en abrégé PHP_SRC_HOME), PHP_SRC_HOME /ext/standard/dl.c, le processus de traitement des clés est le suivant :

PHP_FUNCTION(dl)

PHPAPI PHP_FUNCTION(dl)  
{  
    //...  
    php_dl(filename, MODULE_TEMPORARY, return_value, 0 TSRMLS_CC);  
    //...   
}
Copier après la connexion
php_dl

PHPAPI void php_dl(char *file, int type, zval *return_value, int start_now TSRMLS_DC)  
{  
    if (php_load_extension(file, type, start_now TSRMLS_CC) == FAILURE) {  
       //...  
}
Copier après la connexion
php_load_extension

PHPAPI int php_load_extension(char *filename, int type, int start_now TSRMLS_DC) {  
    //文件名解析相关  
      
    //加载动态链接库  
    handle = DL_LOAD(libpath);  
      
    //加载错误处理  
      
    //获取模块的get_module函数(重点, 模块初始入口)  
    get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "get_module");  
      
    //get_module函数获取错误处理  
      
    //那个get_module()得到struct zend_module_entry  
    module_entry = get_module();  
    //...  
      
    //注册模块(重点, 函数在这里被注册)  
    if ((module_entry = zend_register_module_ex(module_entry TSRMLS_CC)) == NULL) {  
        //错误处理  
    }  
      
    //模块启动(重点, PHP_MINIT_FUNCTION)  
    if ((type == MODULE_TEMPORARY || start_now) && zend_startup_module_ex(module_entry TSRMLS_CC) == FAILURE) {  
        //错误处理  
    }  
      
    //模块请求启动(重点, PHP_RINIT_FUNCTION)  
    if ((type == MODULE_TEMPORARY || start_now) && module_entry->request_startup_func) {  
        //错误处理  
    }  
    return SUCCESS;  
}
Copier après la connexion
Problèmes clés du processus

fonction get_module

get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL( handle, "get_module");

Cette phrase de code après expansion de la macro est la suivante :

get_module = (zend_module_entry *(*)(void)) dlsym(handle, "_get_module" );

Google ce que fait la fonction dlsym() , nous pouvons facilement comprendre ce code. Il s'agit d'un

pointeur de fonction obtenu à partir de la bibliothèque de liens dynamiques qui vient d'être chargée, qui est la fonction get_module que nous avons. défini lors du développement du module.

Après expansion de la macro (sans tenir compte des attributs pour GNU et extern "C" pour C++) :

zend_module_entry *get_module(void) { return &sample_module_entry }

En mettant dl() Le processus de chargement de la fonction est lié à la définition lors du développement du module. Nous pouvons voir que lorsque le module est chargé, notre zend_module_entry personnalisé est transmis à partir d'ici

Inscription du module<. 🎜>

module_entry = zend_register_module_ex(module_entry TSRMLS_CC)

Le code ci-dessus est extrait de la fonction php_load_extension Nous continuons à explorer zend_register_module_ex() pour trouver l'enregistrement de fonction qui nous intéresse :

if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type TSRMLS_CC)==FAILURE) {

Continuez à explorer la fonction zend_register_functions :

Récupérer la fonction Lors de la création de la table des symboles, une macro CG est utilisée :
ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) /* {{{ */ {  
    //...  
      
    //重点 如果没有函数符号表, 取全局函数符号表  
    if (!target_function_table) {  
        target_function_table = CG(function_table);  
    }  
      
    //...  
      
    //重点 循环zend_function_entry[]  
    while (ptr->fname) {  
        //向函数符号表增加函数  
        if (zend_hash_add(target_function_table, lowercase_name, fname_len+1, &function, sizeof(zend_function), (void**)?_function) == FAILURE) {  
            //错误处理  
        }  
      
        //...  
      
        //准备遍历zend_function_entry[]下一个元素  
        ptr++;  
      
        //...  
    }  
    //...  
      
    return SUCCESS;  
}
Copier après la connexion

target_function_table = CG(function_table);

Nous résolvons cette macro dans deux situations :

Enfin, ce qu'ils obtiennent est l'élément function_table dans une
//非线程安全  
compiler_globals.function_table  
      
//线程安全  
(((zend_compiler_globals *) (*((void ***) tsrm_ls))[ compiler_globals_id - 1])-> function_table)
Copier après la connexion
structure struct

zend_compiler_globals, qui est une HashTable La boucle suivante est facile à comprendre. . Lors du développement du module, utilisez la fonction dans zend_function_entry. Vous pouvez ajouter la traversée à la HashTable

Démarrage du module/Démarrage de la demande de module

Ces deux parties sont faciles à comprendre et correspondent. à PHP_MINIT_FUNCTION() et PHP_RINIT_FUNCTION respectivement dans le développement de modules ()

.

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!

Étiquettes associées:
source:php.cn
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal