Heim  >  Artikel  >  php教程  >  PHP-Kernel-Analyse (2)

PHP-Kernel-Analyse (2)

黄舟
黄舟Original
2016-12-19 11:06:111102Durchsuche

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();
#include 141642a285ad26cf7e55efeead7f8373

jmp_buf env;
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ühren

3 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 aus

5 Stellen Sie abschließend das Bailout in der globalen Variablen

wieder her
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    }
Hier gibt es möglicherweise zwei Zweifel. Was ist, wenn in exec_try kein longjmp vorhanden ist? Dann führen Sie einfach exec_try direkt aus und überspringen Sie exec_catch. Dies ist auch die Standardmethode zur Verwendung von setjmp und longjmp zur Implementierung von Try Catch.


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)!

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
Vorheriger Artikel:PHP-Kernel-Analyse (1)Nächster Artikel:PHP-Kernel-Analyse (1)