首頁  >  文章  >  php教程  >  php內核分析(二)

php內核分析(二)

黄舟
黄舟原創
2016-12-19 11:06:111104瀏覽

摘要:這裡閱讀的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提供的方法。

jmp_buf env;

void foo() {    

printf("before jmpn");    


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 先保存全域變數裡面的bailout

2 使用setjmp來做跳轉執行下面的程式

3 執行exec_try

4 如果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)!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn