PHP execute

Jun 23, 2016 pm 02:37 PM

修改一下文章,之前没说明问题。

主要说明一下PHP的执行过程,涉及到函数执行流程,PHP 的函数让PHP强大的特点之一,暂时不讨论类。PHP 的作用域控制只有两处,函数和类,在实际中感觉函数控制作用域的概念更多一点。

函数分为用户自定义函数,和内部函数。内部函数是php用C 或者是C++编写,这里分析的时候,不会涉及到作用域的切换,在模块初始化的时候就会加载到全局的函数表中EG(function_table)。

内部函数,用户自定义函数,op_array 三者的数据结构如下所示:

struct _zend_op_array {	/* Common elements */	zend_uchar type;	char *function_name;			zend_class_entry *scope;	zend_uint fn_flags;	union _zend_function *prototype;	zend_uint num_args;	zend_uint required_num_args;	zend_arg_info *arg_info;	zend_bool pass_rest_by_reference;	unsigned char return_reference;	/* END of common elements */	zend_bool done_pass_two;	zend_uint *refcount;	zend_op *opcodes;	zend_uint last, size;	zend_compiled_variable *vars;	int last_var, size_var;	zend_uint T;	zend_brk_cont_element *brk_cont_array;	int last_brk_cont;	int current_brk_cont;	zend_try_catch_element *try_catch_array;	int last_try_catch;	/* static variables support */	HashTable *static_variables;	zend_op *start_op;	int backpatch_count;	zend_uint this_var;	char *filename;	zend_uint line_start;	zend_uint line_end;	char *doc_comment;	zend_uint doc_comment_len;	zend_uint early_binding; /* the linked list of delayed declarations */	void *reserved[ZEND_MAX_RESERVED_RESOURCES];};typedef struct _zend_internal_function {	/* Common elements */	zend_uchar type;	char * function_name;	zend_class_entry *scope;	zend_uint fn_flags;	union _zend_function *prototype;	zend_uint num_args;	zend_uint required_num_args;	zend_arg_info *arg_info;	zend_bool pass_rest_by_reference;	unsigned char return_reference;	/* END of common elements */	void (*handler)(INTERNAL_FUNCTION_PARAMETERS);	struct _zend_module_entry *module;} zend_internal_function;typedef union _zend_function {	zend_uchar type;	/* MUST be the first element of this struct! */	struct {		zend_uchar type;  /* never used */		char *function_name;		zend_class_entry *scope;		zend_uint fn_flags;		union _zend_function *prototype;		zend_uint num_args;		zend_uint required_num_args;		zend_arg_info *arg_info;		zend_bool pass_rest_by_reference;		unsigned char return_reference;	} common;	zend_op_array op_array;	zend_internal_function internal_function;} zend_function;typedef struct _zend_function_state {	zend_function *function;	void **arguments;} zend_function_state
Nach dem Login kopieren

这三个数据结构之间可以相互转换,我在上面也列出了一个_zend_function_state 的数据结构,会讲op_array 中的 function 赋值给执行数据_zend_execute_data 的function_state字段的 function,从而将普通代码中切入一个函数,对于作用域的切换稍后说明。

在excute 执行过程中,有EX(function_state).function = (zend_function *) op_array;可以说明一切。

一个重要的数据结构:

struct _zend_execute_data {	struct _zend_op *opline;	zend_function_state function_state;	zend_function *fbc; /* Function Being Called */	zend_class_entry *called_scope;	zend_op_array *op_array;	zval *object;	union _temp_variable *Ts;	zval ***CVs;	HashTable *symbol_table;	struct _zend_execute_data *prev_execute_data;	zval *old_error_reporting;	zend_bool nested;	zval **original_return_value;	zend_class_entry *current_scope;	zend_class_entry *current_called_scope;	zval *current_this;	zval *current_object;	struct _zend_op *call_opline;}
Nach dem Login kopieren

用于保存执行期间的数据,在作用域切换的时候起至关重要的作用。

ZEND_API void execute(zend_op_array *op_array TSRMLS_DC){	zend_execute_data *execute_data;	zend_bool nested = 0;	zend_bool original_in_execution = EG(in_execution);	if (EG(exception)) {		return;	}	EG(in_execution) = 1;zend_vm_enter:	/* Initialize execute_data */	execute_data = (zend_execute_data *)zend_vm_stack_alloc(		ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)) +		ZEND_MM_ALIGNED_SIZE(sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2)) +		ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T TSRMLS_CC);	EX(CVs) = (zval***)((char*)execute_data + ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)));	memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var);	EX(Ts) = (temp_variable *)(((char*)EX(CVs)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2)));	EX(fbc) = NULL;	EX(called_scope) = NULL;	EX(object) = NULL;	EX(old_error_reporting) = NULL;	EX(op_array) = op_array;	EX(symbol_table) = EG(active_symbol_table);	EX(prev_execute_data) = EG(current_execute_data);	EG(current_execute_data) = execute_data;	EX(nested) = nested;	nested = 1;	if (op_array->start_op) {		ZEND_VM_SET_OPCODE(op_array->start_op);	} else {		ZEND_VM_SET_OPCODE(op_array->opcodes);	}	if (op_array->this_var != -1 && EG(This)) { 		Z_ADDREF_P(EG(This)); /* For $this pointer */		if (!EG(active_symbol_table)) {			EX(CVs)[op_array->this_var] = (zval**)EX(CVs) + (op_array->last_var + op_array->this_var);			*EX(CVs)[op_array->this_var] = EG(This);		} else {			if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void**)&EX(CVs)[op_array->this_var])==FAILURE) {				Z_DELREF_P(EG(This));			}		}	}	EG(opline_ptr) = &EX(opline);	EX(function_state).function = (zend_function *) op_array;	EX(function_state).arguments = NULL;		while (1) {    	int ret;#ifdef ZEND_WIN32		if (EG(timed_out)) {			zend_timeout(0);		}#endif		if ((ret = EX(opline)->handler(execute_data TSRMLS_CC)) > 0) {			switch (ret) {				case 1:					EG(in_execution) = original_in_execution;					return;				case 2:					op_array = EG(active_op_array);					goto zend_vm_enter;				case 3:					execute_data = EG(current_execute_data);				default:					break;			}		}	}	zend_error_noreturn(E_ERROR, "Arrived at end of main loop which shouldn't happen");}
Nach dem Login kopieren

执行期间 有EX(prev_execute_data) = EG(current_execute_data);会保存一下现场,

然后EG(current_execute_data) = execute_data;

当执行到函数的op_array时,EG(active_op_array) = &EX(function_state).function->op_array;

会执行到

   case 2:
     op_array = EG(active_op_array);
     goto zend_vm_enter;

当函数将要执行完毕或者返回的时候,可以主动调用return 或者PHP 会自动放回一个NULL,然后是zend_do_return 生成 ZEND_RETURN的opcode ,根据类型不同会调用几个不同的函数,但总之会调用一个名为zend_leave_helper_SPEC 的函数,其中:

EG(current_execute_data) = EX(prev_execute_data);会将返回以前的场景,保证回到执行函数以前的作用域。

个人觉得关键的是以上的一些数据结构,以及相互之间的联系。

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

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Arbeiten mit Flash -Sitzungsdaten in Laravel Arbeiten mit Flash -Sitzungsdaten in Laravel Mar 12, 2025 pm 05:08 PM

Laravel vereinfacht die Behandlung von temporären Sitzungsdaten mithilfe seiner intuitiven Flash -Methoden. Dies ist perfekt zum Anzeigen von kurzen Nachrichten, Warnungen oder Benachrichtigungen in Ihrer Anwendung. Die Daten bestehen nur für die nachfolgende Anfrage standardmäßig: $ Anfrage-

Curl in PHP: So verwenden Sie die PHP -Curl -Erweiterung in REST -APIs Curl in PHP: So verwenden Sie die PHP -Curl -Erweiterung in REST -APIs Mar 14, 2025 am 11:42 AM

Die PHP Client -URL -Erweiterung (CURL) ist ein leistungsstarkes Tool für Entwickler, das eine nahtlose Interaktion mit Remote -Servern und REST -APIs ermöglicht. Durch die Nutzung von Libcurl, einer angesehenen Bibliothek mit Multi-Protokoll-Dateien, erleichtert PHP Curl effiziente Execu

PHP -Protokollierung: Best Practices für die PHP -Protokollanalyse PHP -Protokollierung: Best Practices für die PHP -Protokollanalyse Mar 10, 2025 pm 02:32 PM

Die PHP -Protokollierung ist für die Überwachung und Debugie von Webanwendungen von wesentlicher Bedeutung sowie für das Erfassen kritischer Ereignisse, Fehler und Laufzeitverhalten. Es bietet wertvolle Einblicke in die Systemleistung, hilft bei der Identifizierung von Problemen und unterstützt eine schnellere Fehlerbehebung

Vereinfachte HTTP -Reaktion verspottet in Laravel -Tests Vereinfachte HTTP -Reaktion verspottet in Laravel -Tests Mar 12, 2025 pm 05:09 PM

Laravel bietet eine kurze HTTP -Antwortsimulationssyntax und vereinfache HTTP -Interaktionstests. Dieser Ansatz reduziert die Code -Redundanz erheblich, während Ihre Testsimulation intuitiver wird. Die grundlegende Implementierung bietet eine Vielzahl von Verknüpfungen zum Antworttyp: Verwenden Sie Illuminate \ Support \ facades \ http; Http :: fake ([ 'Google.com' => 'Hallo Welt',, 'github.com' => ['foo' => 'bar'], 'Forge.laravel.com' =>

12 Beste PHP -Chat -Skripte auf Codecanyon 12 Beste PHP -Chat -Skripte auf Codecanyon Mar 13, 2025 pm 12:08 PM

Möchten Sie den dringlichsten Problemen Ihrer Kunden in Echtzeit und Sofortlösungen anbieten? Mit Live-Chat können Sie Echtzeitgespräche mit Kunden führen und ihre Probleme sofort lösen. Sie ermöglichen es Ihnen, Ihrem Brauch einen schnelleren Service zu bieten

Erklären Sie das Konzept der späten statischen Bindung in PHP. Erklären Sie das Konzept der späten statischen Bindung in PHP. Mar 21, 2025 pm 01:33 PM

In Artikel wird die in PHP 5.3 eingeführte LSB -Bindung (LSB) erörtert, die die Laufzeitauflösung der statischen Methode ermöglicht, um eine flexiblere Vererbung zu erfordern. Die praktischen Anwendungen und potenziellen Perfo von LSB

Anpassung/Erweiterung von Frameworks: So fügen Sie benutzerdefinierte Funktionen hinzu. Anpassung/Erweiterung von Frameworks: So fügen Sie benutzerdefinierte Funktionen hinzu. Mar 28, 2025 pm 05:12 PM

In dem Artikel werden Frameworks hinzugefügt, das sich auf das Verständnis der Architektur, das Identifizieren von Erweiterungspunkten und Best Practices für die Integration und Debuggierung hinzufügen.

See all articles