青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

無我

讓內心永遠燃燒著偉大的光明的精神之火!
靈活的思考,嚴謹的實現
豪邁的氣魄、頑強的意志和周全的思考

線程本地存儲TLS(Thread Local Storage)的原理和實現——分類和原理

本文為線程本地存儲TLS系列之分類和原理。

一、TLS簡述和分類

我們知道在一個進程中,所有線程是共享同一個地址空間的。所以,如果一個變量是全局的或者是靜態的,那么所有線程訪問的是同一份,如果某一個線程對其進行了修改,也就會影響到其他所有的線程。不過我們可能并不希望這樣,所以更多的推薦用基于堆棧的自動變量或函數參數來訪問數據,因為基于堆棧的變量總是和特定的線程相聯系的。

不過如果某些時候(比如可能是特定設計的dll),我們就是需要依賴全局變量或者靜態變量,那有沒有辦法保證在多線程程序中能訪問而不互相影響呢?答案是有的。操作系統幫我們提供了這個功能——TLS線程本地存儲。TLS的作用是能將數據和執行的特定的線程聯系起來。

實現TLS有兩種方法:靜態TLS和動態TLS。以下我們將分別說明這兩類TLS。

 

二、靜態TLS

1、使用靜態TLS

之所以先講靜態TLS,是因為他在代碼中使用時非常簡單,我們只需寫類似如下這一句:

__declspec(thread) DWORD myTLSData=0;

我們就為本程序中的每一個線程創建了一個獨立的DWORD數據。

__declspec(thread)的前綴是Microsoft添加給Visual C++編譯器的一個修改符。它告訴編譯器,對應的變量應該放入可執行文件或DLL文件中它的自己的節中。__declspec(thread)后面的變量必須聲明為函數中(或函數外)的一個全局變量或靜態變量。不能聲明一個類型為__declspec(thread)的局部變量,你想,因為局部變量總是與特定的線程相聯系的,如果再加上這個聲明是代表什么意思?

2、靜態TLS原理

靜態TLS的使用是如此簡單,那么當我們寫了如上代碼以后,操作系統和編譯器是怎么處理的呢?

首先,在編譯器對程序進行編譯時,它會將所有聲明的TLS變量放入它們自己的節,這個節的名字是.tls。而后鏈接程序將來自所有對象模塊的所有.tls節組合起來,形成結果的可執行文件或DLL文件中的一個大的完整的.tls節。
然后,為了使含有靜態TLS的程序能夠運行,操作系統必須參與其操作。當TLS應用程序加載到內存中時,系統要尋找可執行文件中的.tls節,并且動態地分配一個足夠大的內存塊,以便存放所有的靜態TLS變量。應用程序中的代碼每次引用其中的一個變量時,就要轉換為已分配內存塊中包含的一個內存位置。因此,編譯器必須生成一些輔助代碼來引用該靜態TLS變量,這將使你的應用程序變得比較大而且運行的速度比較慢。在x86 CPU上,將為每次引用的靜態TLS變量生成3個輔助機器指令。如果在進程中創建了另一個線程,那么系統就要將它捕獲并且自動分配另一個內存塊,以便存放新線程的靜態TLS變量。新線程只擁有對它自己的靜態TLS變量的訪問權,不能訪問屬于其他線程的TLS變量。

以上是包含靜態TLS變量的可執行文件如何運行的情況。我們再來看看DLL的情況:

a、隱式鏈接包含靜態TLS變量的DLL

如果應用程序使用了靜態TLS變量,并且隱式鏈接包含靜態TLS變量的DLL時,當系統加載該應用程序時,它首先要確定應用程序的.tls節的大小,并將這個值與應用程序鏈接的DLL中的所有.tls節的大小相加。當在你的進程中創建線程時,系統自動分配足夠大的內存塊來存放所有應用程序聲明的和所有隱含鏈接的DLL包含的TLS變量。

b、顯式鏈接包含靜態TLS變量的DLL

考慮一下,當我們的應用程序通過調用LoadLibrary,以便顯式鏈接到包含靜態TLS變量的DLL時,會發生什么情況呢?系統必須查看該進程中已經存在的所有線程,并擴大它們的TLS內存塊,以便適應新DLL對內存的需求。另外,如果調用FreeLibrary來釋放包含靜態TLS變量的DLL,那么與進程中的每個線程相關的的TLS內存塊又都應該被壓縮。
對于操作系統來說,這樣的管理任務太重了。所以,雖然系統允許包含靜態TLS變量的庫在運行期進行顯式加載,但是其包含TLS數據卻沒有進行相應的初始化。如果試圖訪問這些數據,就可能導致訪問違規!

所以,請記住:如果某個DLL包含靜態TLS數據,請不要對這個DLL采用顯式鏈接的方式,否則可能會出錯!

 

三、動態TLS

1、使用動態TLS

動態TLS在程序實現中比靜態TLS要稍微麻煩一些,需要通過一組函數來實現:

DWORD TlsAlloc();//返回TLS數組可用位置的索引

BOOL TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue); //將調用線程的TLS數組索引dwTlsIndex處設為值lpTlsValue

LPVOID TlsGetValue(DWORD dwTlsIndex); //返回調用線程的TLS數組dwTlsIndex索引處的值

BOOL TlsFree(DWORD dwTlsIndex); //釋放所有線程的TLS數組位置索引dwTlsIndex,將該位置標記為未使用。

有了以上四個函數,我們可以發現使用動態TLS其實還是很容易很方便的。

2、動態TLS原理

讓我們看看windows用來管理TLS的內部數據結構:


線程本地存儲器的位標志顯示了該進程中所有運行的線程正在使用的一組標志。每個標志均可設置為FREE或者INUSE,表示TLS插槽(slot)是否正在使用。Microsoft保證至少TLS_MINIMUM_AVAILABLE位標志是可供使用的。另外,TLS_MINIMUM_AVAILABLE在WinNT.h中被定義為64。Windows2000將這個標志數組擴展為允許有1000個以上的TLS插槽。

而每一個線程擁有一個自己獨立的TLS slot數組,用于存儲TLS數據。
為了使用動態TLS,我們首先調用TlsAlloc()來命令系統對進程的位標志進行掃描,找到一個可用的位置,并返回該索引;如果找不到,就返回TLS_OUT_OF_INDEXES。事實上,除此之外,TlsAlloc函數還會自動清空所有線程的TLS數組的對應索引的值。這避免以前遺留的值可能引起的問題。
然后,我們就可以調用TlsSetValue函數將對應的索引位保存一個特定的值,可以調用TlsGetValue()來返回該索引位的值。注意,這兩個函數并不執行任何測試和錯誤檢查,我們必須要保證索引是通過TlsAlloc正確分配的。
當所有線程都不需要保留TLS數組某個索引位的時候,應該調用TlsFree。該函數告知系統將進程的位標志數組的index位置為FREE狀態。如果運行成功,函數返回TRUE。注意,如果試圖釋放一個沒有分配的索引位,將產生一個錯誤。
動態TLS的使用相對靜態TLS稍微麻煩一點,但是無論是將其用在可執行文件中還是DLL中,都還是很簡單的。而且當用在DLL中時,沒有由于DLL鏈接方式而可能產生的問題,所以,如果要在DLL中用TLS,又不能保證客戶始終采用隱式鏈接方式,那么請采用動態TLS的實現。

主要參考文檔《windows核心編程》。

posted on 2012-07-04 08:57 Tim 閱讀(19588) 評論(0)  編輯 收藏 引用 所屬分類: 逆向工程windows系統

<2012年4月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

導航

統計

公告

本博客原創文章,歡迎轉載和交流。不過請注明以下信息:
作者:TimWu
郵箱:timfly@yeah.net
來源:m.shnenglu.com/Tim
感謝您對我的支持!

留言簿(9)

隨筆分類(173)

IT

Life

搜索

積分與排名

最新隨筆

最新評論

閱讀排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久国产精品99国产精| 欧美激情精品| 亚洲激情网站| 免费久久99精品国产自| 免费观看亚洲视频大全| 亚洲黄色有码视频| 国产精品99久久久久久www| 亚洲一区二区三区视频| 久久久久国产成人精品亚洲午夜| 久久精品网址| 男女精品网站| 国产精品成人在线| 国产视频一区在线观看一区免费| 伊人狠狠色j香婷婷综合| 亚洲美女少妇无套啪啪呻吟| 亚洲中午字幕| 欧美黄在线观看| 亚洲图片欧美午夜| 麻豆国产精品一区二区三区| 欧美午夜精品久久久久久久| 激情六月婷婷久久| 亚洲免费在线电影| 欧美激情在线| 久久本道综合色狠狠五月| 欧美日本久久| 亚洲激情视频在线播放| 欧美一区二区啪啪| 亚洲精品国产精品国自产观看浪潮| 亚洲午夜极品| 欧美日韩国产高清视频| 亚洲第一精品夜夜躁人人爽| 欧美亚洲免费电影| 亚洲九九九在线观看| 久久久久久久波多野高潮日日| 欧美日韩高清不卡| 亚洲国产精品一区在线观看不卡| 亚洲欧美电影院| 亚洲欧洲在线看| 久久久国产精品一区二区三区| 欧美午夜精品伦理| 99riav久久精品riav| 久久综合成人精品亚洲另类欧美 | 欧美影院成年免费版| 欧美黄免费看| 久久都是精品| 国产美女扒开尿口久久久| 亚洲最新在线视频| 亚洲国产三级在线| 久久综合电影| 一区二区三区在线免费观看| 午夜精品久久久久久久| 一本色道久久综合亚洲精品婷婷 | 亚洲一区二区免费视频| 欧美国产精品| 日韩视频免费看| 欧美激情一区二区三区 | 久久婷婷人人澡人人喊人人爽| 国产精品久久久久久五月尺| 一本色道久久加勒比88综合| 欧美国产一区二区| 蜜臀av性久久久久蜜臀aⅴ四虎| 狠狠色狠狠色综合人人| 久久久久久亚洲精品中文字幕 | 欧美精品亚洲精品| 亚洲人永久免费| 亚洲国产欧美一区二区三区久久| 久久综合久久久久88| 亚洲国产第一| 亚洲国产日韩一区二区| 欧美日韩亚洲一区三区| 亚洲视频大全| 亚洲欧美色一区| 一区视频在线播放| 欧美黄色aaaa| 欧美视频日韩| 久久久久久久久一区二区| 久久久国产亚洲精品| 亚洲欧洲视频| 亚洲一本大道在线| 国模套图日韩精品一区二区| 免费不卡视频| 欧美视频一区二| 久久久视频精品| 欧美日韩国产成人高清视频| 午夜精品福利视频| 老司机成人在线视频| 一区二区久久| 欧美一区国产在线| 亚洲欧洲一区二区三区| 欧美成人久久| 亚洲影院在线| 久久综合九色综合网站 | 亚洲丶国产丶欧美一区二区三区 | 欧美日韩一区综合| 久久精品91| 欧美高清在线一区二区| 午夜精品婷婷| 欧美大片专区| 久久精品亚洲一区| 欧美日韩国产探花| 牛人盗摄一区二区三区视频| 欧美午夜在线观看| 亚洲第一福利视频| 欧美一级欧美一级在线播放| 亚洲国产成人av在线| 亚洲视频高清| 亚洲美女电影在线| 久久久久久亚洲综合影院红桃| 亚洲性线免费观看视频成熟| 鲁鲁狠狠狠7777一区二区| 欧美一站二站| 国产精品高潮呻吟久久av黑人| 欧美激情在线狂野欧美精品| 国内精品模特av私拍在线观看| 一区二区日韩精品| 99av国产精品欲麻豆| 美女国产一区| 免费亚洲电影在线观看| 国内精品久久久久久久影视麻豆| 一区二区三区四区国产| 亚洲老司机av| 欧美精品免费播放| 亚洲高清自拍| 亚洲美女诱惑| 欧美精品福利| 亚洲伦理在线| 亚洲视屏在线播放| 欧美日韩亚洲国产精品| 亚洲精选视频在线| 亚洲无线视频| 欧美日韩二区三区| 亚洲免费激情| 亚洲一区三区视频在线观看| 欧美日韩在线观看一区二区| 亚洲精品美女在线观看| 9国产精品视频| 欧美日韩在线视频观看| 夜夜夜久久久| 欧美一区二区三区久久精品| 国产精品一区免费观看| 亚洲自拍三区| 久久久成人精品| 国内精品久久久久久影视8| 欧美一二三视频| 久久一区二区三区超碰国产精品| 国产亚洲精品久久久久婷婷瑜伽| 亚洲欧美日韩直播| 老司机久久99久久精品播放免费| 极品中文字幕一区| 欧美aa国产视频| 亚洲精品欧美| 亚洲色图综合久久| 国产精品婷婷| 久久久久久久波多野高潮日日| 欧美大片一区| 亚洲视频在线观看三级| 国产伦精品一区| 久久亚洲一区二区| 亚洲理论电影网| 欧美在线视频a| 亚洲激情在线播放| 欧美视频国产精品| 久久精品二区亚洲w码| 美女脱光内衣内裤视频久久网站| 亚洲国产成人91精品| 欧美日韩在线一二三| 欧美一区二区三区免费观看视频| 免费久久99精品国产自| 99这里只有久久精品视频| 国产精品一区二区三区观看 | 亚洲综合精品自拍| 久久野战av| 国产精品乱人伦一区二区| 欧美中在线观看| 亚洲欧洲在线看| 久久久7777| 亚洲新中文字幕| 亚洲欧洲三级电影| 国产一区二区中文字幕免费看| 欧美高清视频一区二区| 午夜精品久久久久久久99黑人| 欧美va日韩va| 欧美自拍丝袜亚洲| 亚洲深夜av| 亚洲国产日韩欧美在线图片 | 国内精品久久久久久影视8| 欧美日韩美女在线观看| 久久人人爽人人爽爽久久| 亚洲天堂av高清| 亚洲日韩欧美视频| 欧美成人中文| 久久久久久久久久久久久女国产乱| 日韩亚洲欧美成人一区| 国产亚洲一区二区精品| 国产精品wwwwww| 欧美日韩视频| 欧美日韩高清不卡| 欧美精品一区二| 欧美mv日韩mv国产网站| 久久久水蜜桃av免费网站|