摘要:這裡閱讀的php版本為PHP-7.1.0 RC3,閱讀程式碼的平台為linuxZTS我們會看到文章中有很多地方是:#ifdef ZTS # define CG(v) ZEND_TSRMG(compiler_globals_id, zend_compiler_globals * ) #else # define CG(v) (compi ...
這裡閱讀的php版本為PHP-7.1.0 RC3,閱讀程式碼的平台為linux
ZTS
我們會看到文章中有很多地方是:
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
這裡的ZTS是個什麼概念呢。也就結束了。一個層來專門處理線程安全問題。 -enable-maintainer-zts 選項, Windows 平台為--enable-zts)這個就是這裡的ZTS的由來。屬性,在執行緒安全下取得的是透過ZEND_TSREMG方法來取得。
這個是什麼意思呢,需要先理解下setjmp和longjmp,這兩個函數是linux提供的方法。
int ret = setj(Fanv);
return ;
} else {
printf("return %dn", ret);
}
printf("after jmpn");
}
int main(int argc, char* argv[]) {
foo();
longjmp(env, 999);
return 0;
}// 輸出:
/* before jmp
return 999
after jmp */
上面的這個例子,setjmp的時候相當於程序片段1把主動權交出來,然後執行if(ret == 0)下面的程序,直到遇到longjmp,把執行權還給了片段1,而設定jmp_buf為999,片段1繼續執行,發現了ret!=0,就輸出return 999。
好了,回到這個程式:
1 zend_try { 2 ...exec_try 3 } zend_catch { 4 ...exec_catch 5 } zend_end_try();
這個程式裡面的exec_try程式碼區裡面,在遇到錯誤的時候,需要回傳的時候,就會包含一個longjmp函數的呼叫。這樣,就形成了我們平常呼叫try...catch...finnal的功能:
1 先保存全域變數裡面的bailout2 使用setjmp來做跳轉執行下面的程式
3 執行exec_try4 如果exec_try這個程式碼片段裡面有longjmp,而且longjmp回傳非0(一般也確實非0),就執行exec_catch
5 最後,把全域變數裡面的bailout還原這裡可能會有兩個疑惑,如果exec_try裡面沒有longjmp怎麼辦,那就直接只執行了exec_try,就跳過exec_catch了。這個也是標準的用setjmp和longjmp實作try catch的寫法。 這兩個的實作彌補了goto關鍵字只能在函數內部進行跳躍的限制。這個叫做「長跳轉」。 所以在PHP程式碼中,如果你執行的函數有可能拋出異常。不妨使用這個方式把你要執行的程序放在裡面。 以上就是php核心分析(二)的內容,更多相關內容請關注PHP中文網(www.php.cn)!