Heim  >  Artikel  >  Backend-Entwicklung  >  Detaillierte Erläuterung des Aufrufs und Ausführungsprozesses benutzerdefinierter PHP-Funktionen

Detaillierte Erläuterung des Aufrufs und Ausführungsprozesses benutzerdefinierter PHP-Funktionen

伊谢尔伦
伊谢尔伦Original
2017-06-27 09:37:393887Durchsuche

Für den Aufruf einer Funktion sind einige grundlegende Informationen erforderlich, z. B. der Name der Funktion, Parameter und die Definition der Funktion (d. h. der spezifische Ausführungsinhalt der Funktion). Wenn eine Funktion definiert ist und wir sie ausführen, kennen Sie natürlich den Namen dieser Funktion, welche Parameter beim Aufruf übergeben werden und den Operationsinhalt der Funktion. Allerdings kann die Zend-Engine den PHP-Quellcode nicht so „verstehen“ wie wir. Sie muss den Code verarbeiten, bevor er ausgeführt werden kann. Beginnen wir mit den folgenden zwei kleinen Beispielen:

<?php
    function foo(){
        echo "I&#39;m foo!";
    }   
    foo();
?>

Werfen wir einen Blick auf die entsprechenden Opcodes:

Funktionsname: (null)line # * op return Operanden

------------------------------- -----------------------

                                                                                                                                               DO_FCALL                    
                                                                                                                                                                                                                                                                                          # * op - ------------------------------------------------- - -----------------
4 0 > ECHO 1 1 > RETURN                                                                                                             >
Die oben aufgeführten Opcodes enthalten einige entfernte Peripherieinformationen Opcodes des Funktionsteils werden während der Ausführung getrennt. Dies ist besonders wichtig für die Ausführung der Funktion. Konzentrieren wir uns nun auf den Aufruf der Funktion foo. Der OPCODE, der foo aufruft, ist „DO_FCALL“. Wenn DO_FCALL eine Funktionsaufrufoperation ausführt, sucht ZE nach dem Funktionsnamen in der Funktionstabelle (wie oben erwähnt, wird der Funktionsname hier von str_tolower verarbeitet, daher ist der Funktionsname von PHP nicht groß- und kleinschreibungspflichtig). -sensitive) Die Definition der Funktion. Wenn sie nicht vorhanden ist, wird die

Fehlermeldung

„Aufruf einer undefinierten Funktion xxx()“ gemeldet. Wenn sie vorhanden ist, wird der zend_function-Strukturzeiger der Funktion gemeldet zurückgegeben werden und dann anhand des Werts von function.type beurteilt werden. Unabhängig davon, ob es sich bei der Funktion um eine
interne Funktion

oder eine benutzerdefinierte Funktion handelt, rufen Sie zend_execute_internal (zend_internal_function.handler) auf oder rufen Sie zend_execute direkt auf, um das darin enthaltene zend_op_array auszuführen diese Funktion.


Ausführung der Funktion

Aufmerksame Leser bemerken möglicherweise, dass es beim Aufruf der Funktion und in der Funktionsdefinition in den obigen Opcodes einen „Funktionsnamen“ gibt. Tatsächlich ist der Benutzer

definiert die Funktion. Die Ausführung von

unterscheidet sich nicht von der Ausführung anderer Anweisungen. Im Wesentlichen unterscheiden sich die PHP-Anweisungen in der Funktion nicht von den PHP-Anweisungen außerhalb der Funktion. Der größte Unterschied im Funktionskörper selbst liegt in seiner Ausführungsumgebung. Das wichtigste Merkmal dieser „Ausführungsumgebung“ ist der Umfang der Variablen . Wie wir alle wissen, können innerhalb einer Funktion definierte Variablen nicht direkt außerhalb der Funktion verwendet werden und umgekehrt. Wenn die Funktion ausgeführt wird, müssen dann die Umgebungsinformationen vor dem Aufrufen der Funktion gespeichert werden. Nachdem die Funktion ausgeführt wurde, werden auch diese Umgebungsinformationen wiederhergestellt, sodass das gesamte Programm weiterhin ausgeführt werden kann.

内部函数的执行与用户函数不同。用户函数是php语句一条条“翻译”成op_line组成的一个op_array,而内部函数则是用C来实现的,因为执行环境也是C环境, 所以可以直接调用。如下面的例子:

<?php
    $foo = &#39;test&#39;;
    print_r($foo);
?>

生成的opcodes中,内部函数和用户函数的处理都是由DO_FCALL来进行的。而在其具体实现的zend_do_fcall_common_helper_SPEC()中, 则对是否为内部函数进行了判断,如果是内部函数,则使用一个比较长的调用

((zend_internal_function *) EX(function_state).function)->handler(opline->extended_value, EX_T(opline->result.u.var).var.ptr, EX(function_state).function->common      .return_reference?&EX_T(opline->result.u.var).var.ptr:NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);

上面这种方式的内部函数是在zend_execute_internal函数没有定义的情况下。而在而在Zend/zend.c文件的zend_startup函数中,

zend_execute_internal = NULL;

此函数确实被赋值为NULL。于是我们在if (!zend_execute_internal)判断时会成立,所以我们是执行那段很长的调用。 那么,这段很长的调用到底是什么呢?以我们常用的 count函数为例。在4a863a0d9769be17e9a49a855df6b6bb>中, 我们知道内部函数所在的结构体中 有一个handler指针指向此函数需要调用的内部定义的C函数。 这些内部函数在模块初始化时就以扩展的函数的形式加载到EG(function_table)。其调用顺序:

php_module_startup --> php_register_extensions --> zend_register_internal_module
--> zend_register_module_ex --> zend_register_functions
 
zend_register_functions(NULL, module->functions, NULL, module->type TSRMLS_CC)

在standard扩展中。module的定义为:

zend_module_entry basic_functions_module = {
    STANDARD_MODULE_HEADER_EX,
    NULL,
    standard_deps,
    "standard",                 /* extension name */
    basic_functions,            /* function list */
    ... //省略}

从上面的代码可以看出,module->functions是指向basic_functions。在basic_functions.c文件中查找basic_functions的定义。

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des Aufrufs und Ausführungsprozesses benutzerdefinierter PHP-Funktionen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
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