奶头挺立呻吟高潮av全片,成人试看120秒体验区,性欧美极品v,A片高潮抽搐揉捏奶头视频

php語言

php內核分析之ZTS和zend-try

時間:2024-07-18 13:02:23 php語言 我要投稿
  • 相關推薦

php內核分析之ZTS和zend-try

  在學習PHP的同學對內核有沒有疑問呢?下面是百分網小編精心為大家整理的php內核分析之ZTS和zend_try,希望對大家有幫助,更多內容請關注應屆畢業生網!

  這里閱讀的php版本為PHP-7.1.0 RC3,閱讀代碼的平臺為linux

  我們會看到文章中有很多地方是:

  #ifdef ZTS

  # define CG(v) ZEND_TSRMG(compiler_globals_id, zend_compiler_globals *, v)

  #else

  # define CG(v) (compiler_globals.v)

  extern ZEND_API struct _zend_compiler_globals compiler_globals;

  #endif

  這里的ZTS是個什么概念呢。我們經常使用的php都是運行在單進程,單線程環境,比如cgi,都是一個請求進來,就一個進程為它服務,當請求結束了,進程也就結束了。所以比如像全局變量,php內核就沒有考慮多線程同時修改獲取的時候線程安全問題。后來,php漸漸也在往單進程多線程服務器方向發展。那么這個時候,就會需要有一個層來專門處理線程安全問題。這個就是TSRM(Thread Safe Resource Management)。

  但是php默認是關閉線程安全的。在編譯的時候,你可以指定參數開啟編譯一個線程安全版本的php。(--enable-maintainer-zts 選項, Windows 平臺為 --enable-zts)這個就是這里的ZTS的由來。

  比如上面的例子,CG(V) 在非線程安全下獲取的是全局結構compiler_globals結構的v屬性,在線程安全下獲取的是通過ZEND_TSREMG方法來獲取。

  zend_try

  我們會看到zend_try_catch相關的代碼如下:

  zend_try {

  ...exec_try

  } zend_catch {

  ...exec_catch

  } zend_end_try();

  把宏展開,我們可以看到大概代碼如下:

  { \

  JMP_BUF *__orig_bailout = EG(bailout); \

  JMP_BUF __bailout; \

  \

  EG(bailout) = &__bailout; \

  if (SETJMP(__bailout)==0) {

  {

  ...exec_try

  }

  } else { \

  EG(bailout) = __orig_bailout;

  {

  ...exec_catch

  }

  } \

  EG(bailout) = __orig_bailout; \

  }

  這個是什么意思呢,需要先理解下setjmp和longjmp,這兩個函數是linux提供的方法。他們是組合起來使用的,達到協同程序的功能

  #include

  #include

  jmp_buf env;

  void foo() {

  printf("before jmp\n");

  int ret = setjmp(env);

  if(ret == 0) {

  return;

  } else {

  printf("return %d\n", ret);

  }

  printf("after jmp\n");

  }

  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。

  好了,回到這個程序:

  { \

  JMP_BUF *__orig_bailout = EG(bailout); \

  JMP_BUF __bailout; \

  \

  EG(bailout) = &__bailout; \

  if (SETJMP(__bailout)==0) {

  {

  ...exec_try

  }

  } else { \

  EG(bailout) = __orig_bailout;

  {

  ...exec_catch

  }

  } \

  EG(bailout) = __orig_bailout; \

  }

  這個程序里面的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內核分析之ZTS和zend-try】相關文章:

php內核分析之擴展03-20

php內核分析之sapi-module-struct03-20

PHP與ASP的分析對比03-28

php中引用的用法分析04-01

PHP頁面漏洞分析的方法03-27

PHP面試之php自帶的幾個防止sql注入的函數03-03

PHP循環語句用法之—for循環12-06

PHP常用開發工具分析06-27

php入庫和出庫的方法12-02

主站蜘蛛池模板: 汉川市| 仙桃市| 隆尧县| 大渡口区| 顺义区| 娄底市| 麻栗坡县| 定安县| 乳山市| 白水县| 柳河县| 淮阳县| 霸州市| 黑水县| 莎车县| 梅州市| 黑龙江省| 永福县| 女性| 兴安盟| 洛宁县| 汶川县| 沈丘县| 奉节县| 嵩明县| 科技| 洮南市| 渑池县| 云阳县| 鄂州市| 开原市| 通河县| 溧阳市| 辽源市| 大方县| 华亭县| 玛多县| 施甸县| 全南县| 奈曼旗| 历史|