Zusammenfassung: Die hier gelesene PHP-Version ist PHP-7.1.0 RC3 und die Plattform zum Lesen des Codes ist linuxZTS. Wir werden sehen, dass es im Artikel viele Stellen gibt: #ifdef ZTS # define CG(v) ZEND_TSRMG (compiler_globals_id, zend_compiler_globals * , v) #else # define CG(v) (compi...
Die hier gelesene PHP-Version ist PHP-7.1.0 RC3, und die Plattform zum Lesen des Codes ist Linux
ZTS
Wir werden sehen, dass es viele Stellen im Artikel gibt:
1 #ifdef ZTS 2 # define CG(v) ZEND_TSRMG(compiler_globals_id, zend_compiler_globals *, v) 3 #else 4 # define CG(v) (compiler_globals.v) 5 extern ZEND_API struct _zend_compiler_globals compiler_globals; 6 #endif
Was ist das Konzept von ZTS hier? Das PHP, das wir oft verwenden, läuft in einem einzigen -Prozess, Single-Threaded-Umgebung, wie z. B. cgi, wenn eine Anfrage eingeht, wird sie nur von einem Prozess bearbeitet. Wenn die Anfrage endet, berücksichtigt der PHP-Kernel beispielsweise keine Thread-Sicherheitsprobleme Sie werden auch in Richtung Single-Process-Multithread-Server weiterentwickelt. Zu diesem Zeitpunkt wird eine Ebene erforderlich sein, die sich speziell mit Thread-Sicherheitsproblemen befasst PHP ist jedoch standardmäßig deaktiviert. Beim Kompilieren können Sie Parameter angeben, um das Kompilieren einer Thread-sicheren Version von PHP zu ermöglichen (Option --enable-maintainer-zts, Windows-Plattform ist --enable-zts). ). Dies ist der Ursprung von ZTS. Im obigen Beispiel erhält CG(V) beispielsweise das v-Attribut der globalen Struktur „compiler_globals“ unter Nicht-Thread-Sicherheit und ruft es über die Methode ZEND_TSREMG ab unter Thread-Sicherheit.
Wir sehen den Code für zend_try_catch wie folgt:Erweitern Sie das Makro, wir können den ungefähren Code sehen als folgt:
Was bedeutet das? Sie müssen zuerst setjmp und longjmp verstehen. Diese beiden Funktionen werden in Kombination verwendet, um die Funktion von Coroutinen zu erreichen >#include < ;stdio.h>
1 zend_try { 2 ...exec_try 3 } zend_catch { 4 ...exec_catch 5 } zend_end_try();
01 { \ 02 JMP_BUF *__orig_bailout = EG(bailout); \ 03 JMP_BUF __bailout; \ 04 \ 05 EG(bailout) = &__bailout; \ 06 if (SETJMP(__bailout)==0) { 07 { 08 ...exec_try 09 } 10 } else { \ 11 EG(bailout) = __orig_bailout; 12 { 13 ...exec_catch 14 } 15 } \ 16 EG(bailout) = __orig_bailout; \ 17 }
void foo() {
printf ("vor jmpn");
int ret = setjmp(env);
if(ret == 0) {
return;
} else {
printf("return %dn", ret);
}
printf("after jmpn");
}
int main(int argc, char* argv[]) {
foo();
longjmp(env, 999);
return 0;
}// Ausgabe:
/* vor jmp
999 zurückgeben
nach jmp */
Im obigen Beispiel entspricht setjmp der Übergabe der Initiative durch Programmfragment 1 und der anschließenden Ausführung des folgenden Programms if (ret == 0), bis es auf longjmp trifft und das Ausführungsrecht auf Fragment 1 zurückgibt wird abgerufen und jmp_buf wird auf 999 gesetzt. Fragment 1 wird weiterhin ausgeführt und ret!=0 wird gefunden und return 999 wird ausgegeben.
Okay, zurück zu diesem Programm:
Wenn im exec_try-Codesegment in diesem Programm ein Fehler auftritt und Sie zurückkehren müssen, wird dies der Fall sein enthalten einen Aufruf der longjmp-Funktion. Auf diese Weise wird unsere übliche Funktion zum Aufrufen von try...catch...finnal gebildet:1 Speichern Sie zuerst das Bailout in der globalen Variablen
2 Verwenden Sie setjmp, um zu springen und das folgende Programm auszuführen3 Führen Sie exec_try aus
4 Wenn sich longjmp im exec_try-Codesegment befindet und longjmp ungleich 0 zurückgibt (im Allgemeinen ist es tatsächlich ungleich 0), führen Sie exec_catch aus5 Stellen Sie abschließend das Bailout in der globalen Variablen
wieder her01 { \ 02 JMP_BUF *__orig_bailout = EG(bailout); \ 03 JMP_BUF __bailout; \ 04 \ 05 EG(bailout) = &__bailout; \ 06 if (SETJMP(__bailout)==0) { 07 { 08 ...exec_try 09 } 10 } else { \ 11 EG(bailout) = __orig_bailout; 12 { 13 ...exec_catch 14 } 15 } \ 16 EG(bailout) = __orig_bailout; \ 17 }
Die Implementierung dieser beiden gleicht die Einschränkung aus, dass das Schlüsselwort goto nur innerhalb der Funktion springen kann. Dies wird als „Weitsprung“ bezeichnet.
Wenn also in PHP-Code die von Ihnen ausgeführte Funktion möglicherweise eine Ausnahme auslöst. Sie können diese Methode genauso gut verwenden, um das Programm, das Sie ausführen möchten, darin abzulegen.
Das Obige ist der Inhalt der PHP-Kernel-Analyse (2). Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn)!