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

統計

  • 隨筆 - 50
  • 文章 - 42
  • 評論 - 147
  • 引用 - 0

留言簿(6)

隨筆分類

文章分類

Link

搜索

  •  

積分與排名

  • 積分 - 167189
  • 排名 - 159

最新評論

閱讀排行榜

評論排行榜

使用線程局部存儲TLS

Thread local storage (TLS)統一進程的多個線程可以通過由TlsAlloc方法返回的索引值在線程自身的空間內存儲和取回一個值。在以下這個例子里,索引值在進程開始時創建,當各個線程啟動時,會各自申請一塊動態內存并且將內存指針通過TlsSetValue方法存儲到各自的TLS空間中(由先前的索引值標定)。CommonFunc方法使用TlsGetValue方法通過索引取得數據指針。在各個線程結束前,釋放動態內存塊。在進程結束見,調用TlsFree方法釋放索引。

 1#include <windows.h> 
 2#include <stdio.h> 
 3 
 4#define THREADCOUNT 4 
 5DWORD dwTlsIndex; 
 6 
 7VOID ErrorExit(LPSTR); 
 8 
 9VOID CommonFunc(VOID) 
10
11   LPVOID lpvData; 
12 
13// Retrieve a data pointer for the current thread. 
14 
15   lpvData = TlsGetValue(dwTlsIndex); 
16   if ((lpvData == 0&& (GetLastError() != ERROR_SUCCESS)) 
17      ErrorExit("TlsGetValue error"); 
18 
19// Use the data stored for the current thread. 
20 
21   printf("common: thread %d: lpvData=%lx\n"
22      GetCurrentThreadId(), lpvData); 
23 
24   Sleep(5000); 
25}
 
26 
27DWORD WINAPI ThreadFunc(VOID) 
28
29   LPVOID lpvData; 
30 
31// Initialize the TLS index for this thread. 
32 
33   lpvData = (LPVOID) LocalAlloc(LPTR, 256); 
34   if (! TlsSetValue(dwTlsIndex, lpvData)) 
35      ErrorExit("TlsSetValue error"); 
36 
37   printf("thread %d: lpvData=%lx\n", GetCurrentThreadId(), lpvData); 
38 
39   CommonFunc(); 
40 
41// Release the dynamic memory before the thread returns. 
42 
43   lpvData = TlsGetValue(dwTlsIndex); 
44   if (lpvData != 0
45      LocalFree((HLOCAL) lpvData); 
46 
47   return 0
48}
 
49 
50int main(VOID) 
51
52   DWORD IDThread; 
53   HANDLE hThread[THREADCOUNT]; 
54   int i; 
55 
56// Allocate a TLS index. 
57 
58   if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) 
59      ErrorExit("TlsAlloc failed"); 
60 
61// Create multiple threads. 
62 
63   for (i = 0; i < THREADCOUNT; i++
64   
65      hThread[i] = CreateThread(NULL, // default security attributes 
66         0,                           // use default stack size 
67         (LPTHREAD_START_ROUTINE) ThreadFunc, // thread function 
68         NULL,                    // no thread function argument 
69         0,                       // use default creation flags 
70         &IDThread);              // returns thread identifier 
71 
72   // Check the return value for success. 
73      if (hThread[i] == NULL) 
74         ErrorExit("CreateThread error\n"); 
75   }
 
76 
77   for (i = 0; i < THREADCOUNT; i++
78      WaitForSingleObject(hThread[i], INFINITE); 
79 
80   TlsFree(dwTlsIndex);
81
82   return 0
83}
 
84 
85VOID ErrorExit (LPSTR lpszMessage) 
86
87   fprintf(stderr, "%s\n", lpszMessage); 
88   ExitProcess(0); 
89}

90

常用情景:
各個線程所處理的對象有所不同,但是所需要的處理卻可能類似,例如多個線程同時處理多個文件,就可以將文件句柄存在在相應的Tls中,在使用相同的接口進行處理
背景知識:
每個線程除了共享進程的資源外還擁有各自的私有資源:一個寄存器組(或者說是線程上下文);一個專屬的堆棧;一個專屬的消息隊列;一個專屬的Thread Local Storage(TLS);一個專屬的結構化異常處理串鏈。
TLS 是一個良好的Win32 特質,讓多線程程序設計更容易一些。TLS 是一個機制,經由它,程序可以擁有全域變量,但在不同的線程里有不同的值。也就是說,進程中的所有線程都可以擁有全域變量,但這些變量其實是特定對某個線程才有意義。例如,你可能有一個多線程程序,每一個線程都對不同的文件寫文件(也因此它們使用不同的文件handle)。這種情況下,把每一個線程所使用的文件handle 儲存在TLS 中,將會十分方便。當線程需要知道所使用的handle,它可以從TLS 獲得。重點在于:線程用來取得文件handle 的那一段碼在任何情況下都是相同的,而從TLS中取出的文件handle 卻各不相同。非常靈巧,不是嗎?有全域變數的便利,卻又分屬各線程。

 

  雖然TLS 很方便,它并不是毫無限制。在Windows NT 和Windows 95 之中,有64 個DWORD slots 供每一個線程使用。這意思是一個進程最多可以有64 個「對各線程有不同意義」的DWORDs。 雖然TLS 可以存放單一數值如文件handle,更常的用途是放置指針,指向線程的私有資料。有許多情況,多線程程序需要儲存一堆數據,而它們又都是與各線程相關。許多程序員對此的作法是把這些變量包裝為C 結構,然后把結構指針儲存在TLS 中。當新的線程誕生,程序就配置一些內存給該結構使用,并且把指針儲存在為線程保留下來的TLS 中。一旦線程結束,程序代碼就釋放所有配置來的區塊。既然每一個線程都有64 個slots 用來儲存線程自己的數據,那么這些空間到底打哪兒來?在線程的學習中我們可以從結構TDB中看到,每一個thread database 都有64 個DWORDs 給TLS 使用。當你以TLS 函式設定或取出數據,事實上你真正面對的就是那64 DWORDs。好,現在我們知道了原來那些“對各線程有不同意義的全局變量”是存放在線程各自的TDB中阿。
 
    接下來你也許會問:我怎么存取這64個DWORDS呢?我又怎么知道哪個DWORDS被占用了,哪個沒有被占用呢?首先我們要理解這樣一個事實:系統之所以給我們提供TLS這一功能,就是為了方便的實現“對各線程有不同意義的全局變量”這一功能;既然要達到“全局變量”的效果,那么也就是說每個線程都要用到這個變量,既然這樣那么我們就不需要對每個線程的那64個DWORDS的占用情況分別標記了,因為那64個DWORDS中的某一個一旦占用,是所有線程的那個DWORD都被占用了,于是KERNEL32 使用兩個DWORDs(總共64 個位)來記錄哪一個slot 是可用的、哪一個slot 已經被用。這兩個DWORDs 可想象成為一個64 位數組,如果某個位設立,就表示它對應的TLS slot 已被使用。這64 位TLS slot 數組存放在process database 中(在進程一節中的PDB結構中我們列出了那兩個DWORDs)。
 
下面的四個函數就是對TLS進行操作的:

  (1)TlsAlloc  

上面我們說過了KERNEL32 使用兩個DWORDs(總共64 個位)來記錄哪一個slot 是可用的、哪一個slot 已經被用。當你需要使用一個TLS slot 的時候,你就可以用這個函數將相應的TLS slot位置1。 

 (2)TlsSetValue  

TlsSetValue 可以把數據放入先前配置到的TLS slot 中。兩個參數分別是TLS slot 索引值以及欲寫入的數據內容。TlsSetValue 就把你指定的數據放入64 DWORDs 所組成的數組(位于目前的thread database)的適當位置中。  

 (3)TlsGetValue  

這個函數幾乎是TlsSetValue 的一面鏡子,最大的差異是它取出數據而非設定數據。和TlsSetValue 一樣,這個函數也是先檢查TLS 索引值合法與否。如果是,TlsGetValue 就使用這個索引值找到64 DWORDs 數組(位于thread database 中)的對應數據項,并將其內容傳回。  

 (4)TlsFree  

這個函數將TlsAlloc 和TlsSetValue 的努力全部抹消掉。TlsFree 先檢驗你交給它的索引值是否的確被配置過。如果是,它將對應的64 位TLS slots 位關閉。然后,為了避免那個已經不再合法的內容被使用,TlsFree 巡訪進程中的每一個線程,把0 放到剛剛被釋放的那個TLS slot 上頭。于是呢,如果有某個TLS 索引后來又被重新配置,所有用到該索引的線程就保證會取回一個0 值,除非它們再調用TlsSetValue。

posted on 2008-11-27 21:46 pear_li 閱讀(1212) 評論(0)  編輯 收藏 引用 所屬分類: windows kernel

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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国产精品国产精品毛片| 亚洲欧美成人在线| 一区二区三区成人精品| 一本色道久久加勒比88综合| 9l国产精品久久久久麻豆| 日韩视频一区二区| 一区二区冒白浆视频| 亚洲午夜久久久| 性欧美8khd高清极品| 午夜精品一区二区三区电影天堂| 亚洲欧美欧美一区二区三区| 欧美亚洲视频一区二区| 久久视频一区| 欧美风情在线观看| 99国产精品久久| 午夜伦理片一区| 另类专区欧美制服同性| 欧美日本高清| 国产亚洲精品福利| 1024精品一区二区三区| 日韩视频一区二区三区在线播放免费观看| 亚洲精品国精品久久99热| 一区二区av在线| 久久精品欧美日韩| 亚洲国产小视频在线观看| 欧美大片va欧美在线播放| 亚洲欧洲精品一区二区| 亚洲综合首页| 美女尤物久久精品| 国产精品国产a级| 在线免费观看视频一区| 在线视频日本亚洲性| 久久久久久久久久久一区| 亚洲国产视频直播| 欧美亚洲综合另类| 欧美日本在线视频| 亚洲第一在线综合在线| 久久成人免费日本黄色| 日韩亚洲一区二区| 久久人人97超碰国产公开结果| 久久精品国产99| 午夜精品久久久久久久99热浪潮 | 亚洲国产精品精华液2区45| 亚洲精品美女免费| 午夜精品福利视频| 欧美理论在线| 黄色成人免费观看| 午夜国产不卡在线观看视频| 一区二区三区国产盗摄| 欧美成人国产| 午夜精品av| 国产精品第一页第二页第三页| 亚洲精品一线二线三线无人区| 久久精品综合网| 亚洲视频在线看| 欧美日韩国产综合新一区| 狠狠噜噜久久| 久久精品国产第一区二区三区最新章节 | 亚洲性视频网址| 免费在线欧美视频| 精品成人久久| 久久女同精品一区二区| 亚洲欧美另类国产| 国产精品美女www爽爽爽| 亚洲视频在线观看网站| 亚洲高清精品中出| 久久综合色天天久久综合图片| 韩国三级电影一区二区| 久久人人97超碰国产公开结果 | 久久精品国产2020观看福利| 国产精品私拍pans大尺度在线| 亚洲视频观看| 亚洲欧洲日韩综合二区| 欧美国产欧美亚洲国产日韩mv天天看完整 | 先锋a资源在线看亚洲| 亚洲乱码国产乱码精品精| 欧美黄色精品| 日韩一级在线观看| 亚洲精品一区二区网址| 欧美人与禽猛交乱配视频| 一区二区三区四区五区在线| 亚洲毛片一区| 国产精品久久久久aaaa九色| 亚洲男人av电影| 99亚洲一区二区| 欧美午夜电影在线| 午夜精品在线视频| 久久久久久91香蕉国产| 91久久久久久国产精品| 欧美日韩精品久久| 篠田优中文在线播放第一区| 欧美在线观看视频| 亚洲大片在线观看| 亚洲精品午夜| 国产一区二区三区的电影 | 亚洲第一色在线| 欧美午夜宅男影院| 久久亚洲国产成人| 欧美电影在线免费观看网站| 亚洲色图综合久久| 久久国产99| 亚洲视屏在线播放| 欧美伊人精品成人久久综合97| 一区二区三区在线不卡| 99视频精品在线| 亚洲高清在线播放| 亚洲欧美日韩一区二区三区在线| 亚洲韩日在线| 欧美制服丝袜| 亚洲自拍偷拍视频| 欧美国产激情| 老司机精品福利视频| 国产精品久久波多野结衣| 欧美国产激情| 国产日韩欧美二区| aⅴ色国产欧美| 亚洲第一黄网| 久久精品国产视频| 亚洲欧美国产日韩中文字幕| 欧美a级一区二区| 久久综合久久综合九色| 国产精品一区亚洲| 99re在线精品| 亚洲精品午夜| 麻豆精品视频| 另类成人小视频在线| 国产精品一区久久| 日韩一级精品| 日韩一级在线观看| 免费在线亚洲| 免费在线日韩av| 国语自产精品视频在线看抢先版结局 | 久久九九国产| 久久大综合网| 国产伦精品一区二区三区在线观看| 亚洲免费观看视频| 日韩亚洲一区二区| 欧美成年人视频| 亚洲第一综合天堂另类专| 欧美一区二区观看视频| 欧美视频日韩视频在线观看| 亚洲国产一区在线| 亚洲国产欧美在线人成| 久久免费精品日本久久中文字幕| 久久精品国产99精品国产亚洲性色 | 亚洲欧美日韩一区二区三区在线| 欧美国产专区| 亚洲精品一区二区三区蜜桃久 | 久久中文在线| 伊伊综合在线| 美女福利精品视频| 欧美激情片在线观看| 亚洲欧洲一区二区三区在线观看| 久久综合色播五月| 亚洲福利视频免费观看| 夜夜爽夜夜爽精品视频| 欧美三区视频| 亚洲欧美一区二区视频| 久久久久久一区二区| 尤物99国产成人精品视频| 六月天综合网| 亚洲视频日本| 另类尿喷潮videofree | 久久久久国产精品麻豆ai换脸| 国产专区欧美精品| 欧美丰满高潮xxxx喷水动漫| 日韩图片一区| 欧美一级夜夜爽| 在线免费观看日韩欧美| 欧美日韩精选| 欧美怡红院视频| 欧美成人精品1314www| 99国产精品| 国产亚洲一区在线播放| 欧美大片在线看| 午夜精品久久99蜜桃的功能介绍| 欧美福利视频| 午夜亚洲性色视频| 最新国产乱人伦偷精品免费网站| 欧美性jizz18性欧美| 久久久久久久综合狠狠综合| 亚洲精品国产日韩| 久久久人成影片一区二区三区观看 | 国产精品女主播一区二区三区| 欧美在线视频一区二区三区| 91久久精品久久国产性色也91| 香蕉久久夜色精品国产| 亚洲欧洲日本在线| 国产日韩欧美成人| 欧美日韩视频| 久久综合伊人77777蜜臀| 亚洲天堂av在线免费观看| 免费成人小视频| 欧美专区福利在线| 亚洲一区激情| 日韩午夜在线电影| 亚洲福利国产| 国内精品美女在线观看| 欧美三级不卡|