PHP-Kernel-Analyse (7) – Erweiterung
Zusammenfassung: Die hier gelesene PHP-Version ist PHP-7.1.0 RC3 und die Plattform zum Lesen des Codes ist Linux. Lassen Sie uns diese Erweiterung der Reflexion untersuchen. Das Reflection-Erweiterungsverzeichnis befindet sich unter: ext/reflection. Tatsächlich ist der darin enthaltene Code sehr einfach. Eine .h-Datei und eine .c-Datei. Werfen wir zunächst einen Blick auf die .c-Datei und wir werden viel sehen ...
Die hier gelesene PHP-Version ist PHP-7.1.0 RC3, und die Plattform zum Lesen des Codes ist Linux.
Lassen Sie uns die Reflexionserweiterung untersuchen.
Das Reflection-Erweiterungsverzeichnis existiert in: ext/reflection. Tatsächlich ist der darin enthaltene Code sehr einfach. Eine .h-Datei und eine .c-Datei.
Werfen wir zunächst einen Blick auf die .c-Datei. Wir werden viele Makros sehen, die ZEND_METHOD entsprechen
1 ZEND_METHOD(reflection_function, getReturnType) 2 { 3 ... 4 }
:
1 #define ZEND_METHOD(classname, name) ZEND_NAMED_FUNCTION(ZEND_MN(classname##_##name)) 2 #define ZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS) 3 #define ZEND_MN(name) zim_##name 4 #define INTERNAL_FUNCTION_PARAMETERS zend_execute_data *execute_data, zval *return_value
Das ## hier stellt die Verbindung dar. Die Erweiterung lautet tatsächlich:
void zim_reflection_function_getReturnType(zend_execute_data *execute_data, zval *return_value)
Kurz gesagt, wir verwenden ZEND_METHOD, um eine Funktion zim_reflection_function_getReturnType zu definieren. Wie wird sie hier aus dem Ausführungscode aufgerufen?
Okay, wir können den erweiterten Aufrufstapel hier nicht sehen. Dann schauen wir uns mit gdb den Aufrufstapel an.
Schreiben Sie ein Skript mit Reflection-Erweiterung:
1 <?php 2 3 class B 4 { 5 public function test(): B 6 { 7 8 } 9 } 10 11 function getB(): B 12 { 13 14 } 15 16 $rc = new ReflectionMethod('B', 'test'); 17 var_dump((string)$rc->getReturnType(), $rc->getReturnType()); 18 19 $rc = new ReflectionFunction('getB'); 20 var_dump((string)$rc->getReturnType(), $rc->getReturnType());
Verwenden Sie gdb für die Verwaltung. Wir haben uns die Erweiterungsdefinition von getReturnType angesehen und es gibt eine im Erweiterungscode Für die Verwaltung wird die Funktion „reflection_type_factory“ verwendet.
01 (gdb) b reflection_type_factory 02 03 (gdb) run -f /home/xiaoju/software/php7/demo/echo.php 04 05 (gdb) s 06 07 (gdb) bt 08 #0 reflection_type_factory (fptr=0x7ffff6004210, closure_object=0x0, arg_info=0x7ffff6079048, 09 object=0x7ffff60140d0) at /home/xiaoju/webroot/php-src/php-src-master/ext/reflection/php_reflection.c:1280 10 #1 0x0000000000760d23 in ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER (execute_data=0x7ffff6014030) 11 at /home/xiaoju/webroot/php-src/php-src-master/Zend/zend_vm_execute.h:1097 12 #2 0x000000000073fc88 in execute_ex (ex=<value optimized="" out="">) 13 at /home/xiaoju/webroot/php-src/php-src-master/Zend/zend_vm_execute.h:432 14 #3 0x000000000078b670 in zend_execute (op_array=0x7ffff60782a0, return_value=<value optimized="" out="">) 15 at /home/xiaoju/webroot/php-src/php-src-master/Zend/zend_vm_execute.h:474 16 #4 0x00000000006e48a3 in zend_execute_scripts (type=8, retval=0x0, file_count=3) 17 at /home/xiaoju/webroot/php-src/php-src-master/Zend/zend.c:1464 18 #5 0x0000000000684870 in php_execute_script (primary_file=0x7fffffffe090) 19 at /home/xiaoju/webroot/php-src/php-src-master/main/main.c:2541 20 #6 0x000000000078e9ea in do_cli (argc=3, argv=0xee1bc0) 21 at /home/xiaoju/webroot/php-src/php-src-master/sapi/cli/php_cli.c:994 22 #7 0x000000000078f1ea in main (argc=3, argv=0xee1bc0) 23 at /home/xiaoju/webroot/php-src/php-src-master/sapi/cli/php_cli.c:1387 24 (gdb)</value></value>
Okay, Sie können diesen Kontext sehr deutlich sehen:
main->do_cli->php_execute_scripts->zend_execute->execute_ex->ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER->reflection_type_factory
Für main, do_cli, php_execute_scripts, zend_execute,execute_ex können wir gemäß der vorherigen Hauptfunktionsanalyse leicht verstehen die Rolle jeder Funktion. Mit anderen Worten,execute_ex ist die wichtigste Funktion, die tatsächlich Opcode aufruft.
Vergleichen Sie den Opcode dieses Skripts:
01 L1-21 {main}() /home/xiaoju/software/php7/demo/echo.php - 0x7fd6a127f000 + 30 ops 02 L3 #0 NOP 03 L11 #1 NOP 04 L16 #2 NEW "ReflectionMethod" @1 05 L16 #3 SEND_VAL_EX "B" 1 06 L16 #4 SEND_VAL_EX "test" 2 07 L16 #5 DO_FCALL 08 L16 #6 ASSIGN $rc @1 09 L17 #7 INIT_FCALL 112 "var_dump" 10 L17 #8 INIT_METHOD_CALL $rc "getReturnType" 11 L17 #9 DO_FCALL @4 12 L17 #10 CAST @4 ~5 13 L17 #11 SEND_VAL ~5 1 14 L17 #12 INIT_METHOD_CALL $rc "getReturnType" 15 L17 #13 DO_FCALL @6 16 L17 #14 SEND_VAR @6 2 17 L17 #15 DO_ICALL 18 L19 #16 NEW "ReflectionFunction" @8 19 L19 #17 SEND_VAL_EX "getB" 1 20 L19 #18 DO_FCALL 21 L19 #19 ASSIGN $rc @8 22 L20 #20 INIT_FCALL 112 "var_dump" 23 L20 #21 INIT_METHOD_CALL $rc "getReturnType" 24 L20 #22 DO_FCALL @11 25 L20 #23 CAST @11 ~12 26 L20 #24 SEND_VAL ~12 1 27 L20 #25 INIT_METHOD_CALL $rc "getReturnType" 28 L20 #26 DO_FCALL @13 29 L20 #27 SEND_VAR @13 2 30 L20 #28 DO_ICALL 31 L21 #29 RETURN 1
Sie können sehen, dass der Opcode, der $rc->getReturnType() entspricht, #9 DO_FCALL ist
Okay, beginnen wir mitexecute_ex, was vereinfacht werden kann zu:
01 // 最核心的执行opcode的函数 02 ZEND_API void execute_ex(zend_execute_data *ex) 03 { 04 ... 05 while (1) { 06 int ret; 07 if (UNEXPECTED((ret = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)) != 0)) { 08 ... 09 } 10 11 } 12 ... 13 }
Der Handler hier entspricht einem Handler für jeden Opcode-Op, wie z. B. DO_FCALL . Der Handler ist ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER (derselbe wie der gerade von bt angezeigte Stapel)
Der vereinfachte Pseudocode lautet wie folgt:
01 // DO_FCALL这个opcode对应的处理函数 02 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) 03 { 04 ... 05 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { // 如果是用户定义的函数 06 ... 07 zend_execute_ex(call); 08 ... 09 } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { // 如果是内部函数 10 ... 11 if (!zend_execute_internal) { 12 fbc->internal_function.handler(call, ret); // 执行这个internal_function所定义的handler函数,这个就是实际的调用方法了,命名为:zim_[class]_function_[function] 13 } else { 14 zend_execute_internal(call, ret); 15 } 16 ... 17 18 } else { /* ZEND_OVERLOADED_FUNCTION */ 19 ... 20 if (UNEXPECTED(!zend_do_fcall_overloaded(fbc, call, ret))) { 21 HANDLE_EXCEPTION(); 22 } 23 ... 24 } 25 26 fcall_end: 27 ... 28 ZEND_VM_SET_OPCODE(opline + 1); 29 ZEND_VM_CONTINUE(); // 下一条op 30 }
As Sie können sehen, dass die Funktion einen fbc->internal_function.handler enthält. Der Funktionsname, der der internal_function entspricht, ist zim_reflection_function_getReturnType, was der in unserem Erweiterungsmodul definierten Funktion entspricht. Man kann sagen, dass wir hier in die Erweiterung eingetreten sind.
Das Obige ist der Inhalt der PHP-Kernel-Analyse (7) - Erweiterung. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn)!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen



PHP 8.4 bringt mehrere neue Funktionen, Sicherheitsverbesserungen und Leistungsverbesserungen mit einer beträchtlichen Menge an veralteten und entfernten Funktionen. In dieser Anleitung wird erklärt, wie Sie PHP 8.4 installieren oder auf PHP 8.4 auf Ubuntu, Debian oder deren Derivaten aktualisieren. Obwohl es möglich ist, PHP aus dem Quellcode zu kompilieren, ist die Installation aus einem APT-Repository wie unten erläutert oft schneller und sicherer, da diese Repositorys in Zukunft die neuesten Fehlerbehebungen und Sicherheitsupdates bereitstellen.

Um in cakephp4 mit Datum und Uhrzeit zu arbeiten, verwenden wir die verfügbare FrozenTime-Klasse.

CakePHP ist ein Open-Source-Framework für PHP. Es soll die Entwicklung, Bereitstellung und Wartung von Anwendungen erheblich vereinfachen. CakePHP basiert auf einer MVC-ähnlichen Architektur, die sowohl leistungsstark als auch leicht zu verstehen ist. Modelle, Ansichten und Controller gu

Um am Datei-Upload zu arbeiten, verwenden wir den Formular-Helfer. Hier ist ein Beispiel für den Datei-Upload.

Der Validator kann durch Hinzufügen der folgenden zwei Zeilen im Controller erstellt werden.

Die Anmeldung bei CakePHP ist eine sehr einfache Aufgabe. Sie müssen nur eine Funktion verwenden. Sie können Fehler, Ausnahmen, Benutzeraktivitäten und von Benutzern durchgeführte Aktionen für jeden Hintergrundprozess wie Cronjob protokollieren. Das Protokollieren von Daten in CakePHP ist einfach. Die Funktion log() wird bereitgestellt

Visual Studio Code, auch bekannt als VS Code, ist ein kostenloser Quellcode-Editor – oder eine integrierte Entwicklungsumgebung (IDE) –, die für alle gängigen Betriebssysteme verfügbar ist. Mit einer großen Sammlung von Erweiterungen für viele Programmiersprachen kann VS Code c

CakePHP ist ein Open-Source-MVC-Framework. Es erleichtert die Entwicklung, Bereitstellung und Wartung von Anwendungen erheblich. CakePHP verfügt über eine Reihe von Bibliotheken, um die Überlastung der häufigsten Aufgaben zu reduzieren.
