亚洲最大看欧美片,亚洲图揄拍自拍另类图片,欧美精品v国产精品v呦,日本在线精品视频免费

  • 站長資訊網
    最全最豐富的資訊網站

    php之管理全局狀態(tài)

    php之管理全局狀態(tài)

    管理全局狀態(tài)

    在命令式語言中總是需要一些全局空間。在編程 PHP 或擴展時,我們將明確區(qū)分我們所稱的請求綁定全局變量和真正的全局變量。

    請求全局變量是處理請求過程中需要攜帶和記憶信息的全局變量。一個簡單的例子是,您要求用戶在函數參數中提供一個值,并且希望能夠在其他函數中使用它。除了這條信息在幾個 PHP 函數調用中 “保持其值” 之外,它只為當前請求保留該值。下一個來的請求應該什么都不知道。PHP 提供了一種機制來管理請求全局變量,不管選擇了什么樣的多處理模型,我們將在本章后面詳細介紹這一點。

    真正的全局變量是跨請求保留的信息片段。這些信息通常是只讀的。如果您需要寫入這樣的全局變量作為請求處理的一部分,那么 PHP 無法幫助您。如果您使用 線程作為多處理模型, 您需要自己執(zhí)行內存鎖。如果你使用 進程作為多處理模型, 您需要使用自己的IPC(進程間通信)。但是,在PHP擴展編程中不應該出現這種情況。

    相關學習推薦:PHP編程從入門到精通

    管理請求全局變量

    下面是一個使用請求全局的簡單擴展例子:

    /* 真正的 C 全局 */ static zend_long rnd = 0;  static void pib_rnd_init(void) {     /* 在 0 到 100 之間隨機一個數字 */     php_random_int(0, 100, &rnd, 0); }  PHP_RINIT_FUNCTION(pib) {     pib_rnd_init();      return SUCCESS; }  PHP_FUNCTION(pib_guess) {     zend_long r;      if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &r) == FAILURE) {         return;     }      if (r == rnd) {         /* 將數字重置以進行猜測 */         pib_rnd_init();         RETURN_TRUE;     }      if (r < rnd) {         RETURN_STRING("more");     }      RETURN_STRING("less"); }  PHP_FUNCTION(pib_reset) {     if (zend_parse_parameters_none() == FAILURE) {         return;     }      pib_rnd_init(); }

    如你所見,這個擴展在請求開始時挑選一個隨機整型數,之后通過pib_guess()可以嘗試猜到這個數組。一旦猜到,該數字將重置。如果用戶想要手動重置數字,它也可以自己手動調用pib_reset() 去重置數值。
    該隨機數作為一個 C 全局變量實現。如果 PHP 在進程中作為多進程模型的一部分使用不再是個問題,如果之后使用線程,這是不行的。

    注意

    作為提醒,你無需掌握將要使用哪種多進程模型。當你設計擴展時,你必須為這兩種模型做好準備。

    當使用線程,會針對服務器中的每個線程共享一個 C 全局變量。例如我們上面的例子,網絡服務器的每個并行用戶將共享同一個數值。一些可能會一開始就重置數值,而其他則嘗試去猜測它。簡而言之,你清楚地了解了線程的關鍵問題。

    我們必須持久化數據到同一請求,即使運行 PHP 多進程模型會利用線程,也必須讓它綁定到當前請求中。

    使用 TSRM 宏來保護全局空間

    PHP 設計了可以幫助擴展和內核開發(fā)人員處理全局請求的層。該層稱為TSRM (線程安全資源管理) ,并且作為一組宏公開,你必須在任何需要訪問請求綁定全局(讀和寫)的時候使用該宏。

    在多進程模型使用流程的情況下,在后臺,這些宏將解析為類似我們上面顯示的代碼。如我們所見,如果不適用線程,上面的代碼是完全有效的。所以,當使用進程時,這些宏將被擴展為類似的宏。

    首先你要要做的就是聲明一個結構,它將是你所有全局變量的根:

    ZEND_BEGIN_MODULE_GLOBALS(pib)     zend_long rnd; ZEND_END_MODULE_GLOBALS(pib)  /* 解析為 : * * typedef struct _zend_pib_globals { *    zend_long rnd; * } zend_pib_globals; */

    然后,創(chuàng)建一個這樣的全局變量:

    ZEND_DECLARE_MODULE_GLOBALS(pib)  /* 解析為 zend_pib_globals pib_globals; */

    現在,你可以使用全局宏訪問器訪問數據。這個宏是由框架創(chuàng)建的,它應該在你的 php_pib.h 頭文件定義。這看起來是這樣的:

    #ifdef ZTS #define PIB_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(pib, v) #else #define PIB_G(v) (pib_globals.v) #endif

    如你所見,如果沒有啟用 ZTS 模式,即編譯非線程安全的 PHP 和擴展(我們稱之為 NTS模式:非線程安全),宏只是解析到結構中聲明的數據。因此,有以下變化:

    static void pib_rnd_init(void) {     php_random_int(0, 100, &PIB_G(rnd), 0); }  PHP_FUNCTION(pib_guess) {     zend_long r;      if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &r) == FAILURE) {         return;     }      if (r == PIB_G(rnd)) {         pib_rnd_init();         RETURN_TRUE;     }      if (r < PIB_G(rnd)) {         RETURN_STRING("more");     }      RETURN_STRING("less"); }

    注意

    當使用一個進程模型,TSRM 宏解析為對 C 全局變量的訪問。

    當使用線程時,即當你編譯 ZTS PHP,事情變得更復雜。然后,我們看到的所有宏都解析為一些完全不同的東西,在這里很難解釋。基本上,當使用 ZTS 編譯時,TSRM 使用 TLS(線程本地存儲)執(zhí)行了一項艱難的工作。

    注意

    簡而言之,當在 ZTS 編譯時,全局變量將綁定到當前線程。而在 NTS 編譯時,全局變量將綁定到當前進程上。TSRM 宏處理這項艱難的工作。你可能對運作方式感興趣,瀏覽 PHP 源代碼的/TSRM 目錄了解

    贊(0)
    分享到: 更多 (0)
    網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號