Heim > Backend-Entwicklung > PHP-Problem > So passen Sie die Hook-Funktion der PHP-Erweiterung (2) an

So passen Sie die Hook-Funktion der PHP-Erweiterung (2) an

藏色散人
Freigeben: 2023-03-14 14:32:01
nach vorne
2121 Leute haben es durchsucht

Fortsetzung des vorherigen Artikels Lassen Sie uns über den PHP-Lebenszyklus sprechen und sehen, welche Hooks erweitert werden, um was zu tun. Der PHP-Lebenszyklus besteht aus etwa 5 Phasen, der Modulinitialisierungsphase php_module_startup code>, Anforderungsinitialisierungsphase <code>php_request_startup, Skriptausführungsphase php_execute_script, Anforderungsabschaltphase php_request_shutdown, Modulabschaltphase php_module_shutdown , Folgendes wird im CLI-Modus eingeführt. php_module_startup,请求初始化阶段php_request_startup,脚本执行阶段php_execute_script,请求关闭阶段php_request_shutdown,模块关闭阶段php_module_shutdown,下面以cli模式介绍。

php_module_startup

先看看这个阶段做了什么,如果不知道php入口文件在哪,用gdb看看调用栈,gdb ./php

php_module_startup打断点,执行,在看下调用栈,

b php_module_startup
(gdb) r test.php
bt
php_module_startup (sf=0x1406460 <cli_sapi_module>, 
    additional_modules=0x0, num_additional_modules=0)
    at /www/test/php/php-7.4.3/main/main.c:2098
#1  0x00000000008bae7c in php_cli_startup (
    sapi_module=0x1406460 <cli_sapi_module>)
    at /www/test/php/php-7.4.3/sapi/cli/php_cli.c:407
#2  0x00000000008bcc80 in main (argc=2, argv=0x1425af0)
    at /www/test/php/php-7.4.3/sapi/cli/php_cli.c:1323
Nach dem Login kopieren

在调用栈可以清楚看到执行流程,现在到/main/main.c文件看看做了哪些事情,也可以用gdb一步一步的看,这里就讲与php扩展有关的几个地方,这里做的初始化工作,像垃圾回收,请求初始化,注册常量,php.ini配置文件加载等,

先来看看怎么加载模块的

/* startup extensions statically compiled in */
    if (php_register_internal_extensions_func() == FAILURE) {
        php_printf("Unable to start builtin modules\n");
        return FAILURE;
    }
Nach dem Login kopieren

这里是加载php内置的模块,这里只贴出核心功能,先检查依赖

/* Check module dependencies */
    if (module->deps) {
        const zend_module_dep *dep = module->deps;

        while (dep->name) {
            if (dep->type == MODULE_DEP_CONFLICTS) {
                name_len = strlen(dep->name);
                lcname = zend_string_alloc(name_len, 0);
                zend_str_tolower_copy(ZSTR_VAL(lcname), dep->name, name_len);

                if (zend_hash_exists(&module_registry, lcname) || zend_get_extension(dep->name)) {
                    zend_string_efree(lcname);
                    /* TODO: Check version relationship */
                    zend_error(E_CORE_WARNING, "Cannot load module '%s' because conflicting module '%s' is already loaded", module->name, dep->name);
                    return NULL;
                }
                zend_string_efree(lcname);
            }
            ++dep;
        }
    }
Nach dem Login kopieren
if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type)==FAILURE) {
        zend_hash_del(&module_registry, lcname);
        zend_string_release(lcname);
        EG(current_module) = NULL;
        zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name);
        return NULL;
    }
Nach dem Login kopieren

这是内置模块加载原理,现在看看ini里的扩展怎么加载

php_ini_register_extensions();
Nach dem Login kopieren
zend_llist_apply(&extension_lists.functions, php_load_php_extension_cb);
Nach dem Login kopieren

利用这个函数加载

php_load_extension(char *filename, int type, int start_now)
Nach dem Login kopieren

这里面也执行了加载内置模块的功能。

是调用了module->functions,进行模块功能函数注册,现在知道了为什么功能函数要写在helloworld_functions这里吧

zend_module_entry helloworld_module_entry = {
    STANDARD_MODULE_HEADER,
    "helloworld",                    /* Extension name */
    helloworld_functions,            /* zend_function_entry */
    PHP_MINIT(helloworld),                            /* PHP_MINIT - Module initialization */
    NULL,                            /* PHP_MSHUTDOWN - Module shutdown */
    PHP_RINIT(helloworld),            /* PHP_RINIT - Request initialization */
    NULL,                            /* PHP_RSHUTDOWN - Request shutdown */
    PHP_MINFO(helloworld),            /* PHP_MINFO - Module info */
    PHP_HELLOWORLD_VERSION,        /* Version */
    PHP_MODULE_GLOBALS(pib),
    NULL,
    NULL,
    NULL,
    STANDARD_MODULE_PROPERTIES_EX
};
Nach dem Login kopieren

现在看看扩展的几个钩子函数

/* start Zend extensions */
    zend_startup_extensions();
Nach dem Login kopieren

这里的核心就是func(element->data)也就是执行扩展

PHP_MINIT函数

element=l->head;
    while (element) {
        next = element->next;
        if (func(element->data)) {
            DEL_LLIST_ELEMENT(element, l);
        }
        element = next;
    }
Nach dem Login kopieren

现在就知道PHP_MINIT

php_module_startup

Schauen Sie sich zunächst an, was in dieser Phase getan wird. Wenn Sie nicht wissen, wo sich die PHP-Eintragsdatei befindet, sehen Sie sich den Aufrufstapel gdb ./php an. code>

Im php_module_startup Haltepunkt, ausführen, den Aufrufstapel ansehen,

Sie können den Ausführungsprozess im Aufrufstapel deutlich sehen, gehen Sie nun zur Datei /main/main.c Um zu sehen, was getan wurde, können Sie auch gdb verwenden. Sehen Sie sich hier einige Dinge im Zusammenhang mit PHP-Erweiterungen an, z. B. Garbage Collection, Anforderungsinitialisierung und Registrierungskonstanten , Laden der php.ini-Konfigurationsdatei usw.

Werfen wir zunächst einen Blick darauf, wie Module geladen werden 🎜rrreee🎜Hier werden nur die Kernfunktionen veröffentlicht rrreeerrreee🎜Dies ist das Prinzip zum Laden des integrierten Moduls. Sehen wir uns nun an, wie die Erweiterung in ini geladen wird.🎜rrreeerrreee🎜Verwenden Sie diese Funktion zum Laden. 🎜🎜Es heißt module->functions, um die Modulfunktion function zu registrieren. Jetzt wissen wir, warum die Funktion function hier in helloworld_functions geschrieben werden sollte. 🎜rrreee🎜Schauen Sie sich das an die Erweiterung Mehrere Hook-Funktionen 🎜rrreee🎜Der Kern hier ist func(element->data), die Ausführungserweiterung 🎜🎜PHP_MINIT-Funktion🎜rrreee🎜Jetzt wissen Der PHP_MINIT-Hook kann viele Initialisierungsfunktionen ausführen, wie man eine benutzerdefinierte erweiterte Funktionsklasse registriert, wie man erweiterte Variablen in php.ini schreibt, wie man in PHP integrierte Funktionen umschreibt, 🎜rrreee🎜Hier wird das umgeschrieben Die Funktion var_dump registriert eine Personenklasse. Im nächsten Artikel wird erläutert, wie AST durch lexikalische Analyse und Syntaxanalyse des PHP-Codes generiert und anschließend die Opcode-Anweisungen für den Aufruf der Zend-VM kompiliert werden. 🎜🎜Empfohlenes Lernen: „🎜PHP-Video-Tutorial🎜“🎜🎜

Das obige ist der detaillierte Inhalt vonSo passen Sie die Hook-Funktion der PHP-Erweiterung (2) an. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:segmentfault.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage