一区二区久久-一区二区三区www-一区二区三区久久-一区二区三区久久精品-麻豆国产一区二区在线观看-麻豆国产视频

PHP及Zend Engine的線程安全模型分析

不知道怎么回事總是令人不舒服的,因此我通過閱讀源碼和查閱有限的資料簡要了解一下相關機制,本文是我對研究內容的總結。 本文首先解釋了線程安全的概念及php中線程安全的背景,然后詳細研究了php的線程安全機制ZTS(Zend Thread Safety)及具體的實現TSRM,研究內容包括相關數據結構、實現細節及運行機制,最后研究了Zend對于單線程和多線程環境的選擇性編譯問題。

線程安全
線程安全問題,一言以蔽之就是多線程環境下如何安全存取公共資源。我們知道,每個線程只擁有一個私有棧,共享所屬進程的堆。在C中,當一個變量被聲明在任何函數之外時,就成為一個全局變量,這時這個變量會被分配到進程的共享存儲空間,不同線程都引用同一個地址空間,因此一個線程如果修改了這個變量,就會影響到全部線程。這看似為線程共享數據提供了便利,但是php往往是每個線程處理一個請求,因此希望每個線程擁有一個全局變量的副本,而不希望請求間相互干擾。 早期的php往往用于單線程環境,每個進程只啟動一個線程,因此不存在線程安全問題。后來出現了多線程環境下使用php的場景,因此Zend引入了Zend線程安全機制(Zend Thread Safety,簡稱ZTS)用于保證線程的安全。

ZTS的基本原理及實現
基本思想
說起來ZTS的基本思想是很直觀的,不是就是需要每個全局變量在每個線程都擁有一個副本嗎?那我就提供這樣的機制: 在多線程環境下,申請全局變量不再是簡單聲明一個變量,而是整個進程在堆上分配一塊內存空間用作“線程全局變量池”,在進程啟動時初始化這個內存池,每當有線程需要申請全局變量時,通過相應方法調用TSRM(Thread Safe Resource Manager,ZTS的具體實現)并傳遞必要的參數(如變量大小等等),TSRM負責在內存池中分配相應內存區塊并將這塊內存的引用標識返回,這樣下次這個線程需要讀寫此變量時,就可以通過將唯一的引用標識傳遞給TSRM,TSRM將負責真正的讀寫操作。這樣就實現了線程安全的全局變量。下圖給出了ZTS原理的示意圖:
imageThread1和Thread2同屬一個進程,其中各自需要一個全局變量Global Var,TSRM為兩者在線程全局內存池中(黃色部分)各自分配了一個區域,并且通過唯一的ID進行標識,這樣兩個線程就可以通過TSRM存取自己的變量而互不干擾。 下面通過具體的代碼片段看一下Zend具體是如何實現這個機制的。這里我用的是php5.3.8的源碼。 TSRM的實現代碼在php源碼的“TSRM”目錄下。

數據結構
TSRM中比較重要的數據結構有兩個:tsrm_tls_entry和tsrm_resource_type。下面先看tsrm_tls_entry。 tsrm_tls_entry定義在TSRM/TSRM.c中:
復制代碼 代碼如下:
typedef struct _tsrm_tls_entry tsrm_tls_entry;

struct _tsrm_tls_entry {
void **storage;
int count;
THREAD_T thread_id;
tsrm_tls_entry *next;
}

每個tsrm_tls_entry結構負責表示一個線程的所有全局變量資源,其中thread_id存儲線程ID,count記錄全局變量數,next指向下一個節點。storage可以看做指針數組,其中每個元素是一個指向本節點代表線程的一個全局變量。最終各個線程的tsrm_tls_entry被組成一個鏈表結構,并將鏈表頭指針賦值給一個全局靜態變量tsrm_tls_table。注意,因為tsrm_tls_table是一個貨真價實的全局變量,所以所有線程會共享這個變量,這就實現了線程間的內存管理一致性。tsrm_tls_entry和tsrm_tls_table結構的示意圖如下:
imagetsrm_resource_type的內部結構相對簡單一些:
復制代碼 代碼如下:
typedef struct {
size_t size;
ts_allocate_ctor ctor;
ts_allocate_dtor dtor;
int done;
}

tsrm_resource_type;上文說過tsrm_tls_entry是以線程為單位的(每個線程一個節點),而tsrm_resource_type以資源(或者說全局變量)為單位,每次一個新的資源被分配時,就會創建一個tsrm_resource_type。所有tsrm_resource_type以數組(線性表)的方式組成tsrm_resource_table,其下標就是這個資源的ID。每個tsrm_resource_type存儲了此資源的大小和構造、析構方法指針。某種程度上,tsrm_resource_table可以看做是一個哈希表,key是資源ID,value是tsrm_resource_type結構。

實現細節
這一小節分析TSRM一些算法的實現細節。因為整個TSRM涉及代碼比較多,這里揀其中具有代表性的兩個函數分析。 第一個值得注意的是tsrm_startup函數,這個函數在進程起始階段被sapi調用,用于初始化TSRM的環境。由于tsrm_startup略長,這里摘錄出我認為應該注意的地方:
復制代碼 代碼如下:
/* Startup TSRM (call once for the entire process) */
TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debug_level, char *debug_filename)
{
/* code... */

tsrm_tls_table_size = expected_threads;

tsrm_tls_table = (tsrm_tls_entry **) calloc(tsrm_tls_table_size, sizeof(tsrm_tls_entry *));
if (!tsrm_tls_table) {
TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate TLS table"));
return 0;
}
id_count=0;

resource_types_table_size = expected_resources;
resource_types_table = (tsrm_resource_type *) calloc(resource_types_table_size, sizeof(tsrm_resource_type));
if (!resource_types_table) {
TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate resource types table"));
free(tsrm_tls_table);
tsrm_tls_table = NULL;
return 0;
}

/* code... */

return 1;
}

其實tsrm_startup的主要任務就是初始化上文提到的兩個數據結構。第一個比較有意思的是它的前兩個參數:expected_threads和expected_resources。這兩個參數由sapi傳入,表示預計的線程數和資源數,可以看到tsrm_startup會按照這兩個參數預先分配空間(通過calloc)。因此TSRM會首先分配可容納expected_threads個線程和expected_resources個資源的。要看各個sapi默認會傳入什么,可以看各個sapi的源碼(在sapi目錄下),我簡單看了一下:
image可以看到比較常用的sapi如mod_php5、php-fpm和cgi都是預分配一個線程和一個資源,這樣是因為不愿浪費內存空間,而且多數情況下php還是運行于單線程環境。 這里還可以看到一個id_count變量,這個變量是一個全局靜態變量,其作用就是通過自增產生資源ID,這個變量在這里被初始化為0。所以TSRM產生資源ID的方式非常簡單:就是一個整形變量的自增。 第二個需要仔細分析的就是ts_allocate_id,編寫過php擴展的朋友對這個函數肯定不陌生,這個函數...

php技術PHP及Zend Engine的線程安全模型分析,轉載需保留來源!

鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。

主站蜘蛛池模板: 国产91高清 | 亚洲成a人片777777网站 | 69国产精品视频免费 | 香蕉eeww99国产在线观看 | 国产成人亚洲综合欧美一部 | 国产成人午夜91精品麻豆剧场 | 欧美7777| 看全色黄大色大片免费久久怂 | 色一本 | 免费一级毛片不卡不收费 | 亚洲一区免费 | 久久黄视频 | 日韩激情在线 | 另类天堂网 | 成 人 黄 色视频免费播放 | 亚洲福利视频一区二区三区 | 国产女人成人精品视频 | 国产精品久久久福利 | 久久国产网站 | 精品视频在线免费观看 | 岛国免费视频 | 九九99久久精品午夜剧场免费 | 亚洲伊人久久大香线蕉苏妲己 | 亚洲伊人色一综合网 | 色老板视频 | 免费看岛国视频在线观看 | 精品小视频在线 | 91网站在线看 | 久久亚洲精品中文字幕二区 | 国产精品 视频一区 二区三区 | 色在线免费视频 | 愉拍自拍一区首页 | 色噜噜噜噜噜 | 亚洲精品小视频 | 久久综合九色婷婷97 | 视频三区精品中文字幕 | 亚洲综合激情视频 | 国产午夜亚洲精品不卡福利 | 国产精品一区二区三区四区五区 | 欧美大片a特激情刺激 | 涩涩涩在线视频 |