精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

聊一聊 C# 的線程本地存儲(chǔ)TLS到底是什么

開發(fā) 前端
有朋友在后臺(tái)留言讓我說一下C#的 ThreadStatic 線程本地存儲(chǔ)是怎么玩的?這么說吧,C#的ThreadStatic是假的,因?yàn)镃#完全是由CLR(C++)承載的,言外之意C#的線程本地存儲(chǔ),用的就是用C++運(yùn)行時(shí)提供的 __declspec(thread) 或 __thread 來虛構(gòu)的一套玩法,這一篇我們就來簡(jiǎn)單聊一聊。

一:背景

1. 講故事

有朋友在后臺(tái)留言讓我說一下C#的 ThreadStatic 線程本地存儲(chǔ)是怎么玩的?這么說吧,C#的ThreadStatic是假的,因?yàn)镃#完全是由CLR(C++)承載的,言外之意C#的線程本地存儲(chǔ),用的就是用C++運(yùn)行時(shí)提供的 __declspec(thread) 或 __thread 來虛構(gòu)的一套玩法,這一篇我們就來簡(jiǎn)單聊一聊。

二:C# 的線程本地存儲(chǔ)

1. 虛構(gòu)在哪里

在 C# 中使用ThreadStatic就可以將變量和線程進(jìn)行綁定,參考代碼如下:

internal class Program
    {
        [ThreadStatic]
        public static int num = 10;

        static void Main(string[] args)
        {
            Console.WriteLine($"num={num}");

            Debugger.Break();
        }
    }

在 CLR 中如何將 num 與 Thread 綁定呢?研究過 CLR 源碼的朋友應(yīng)該知道是用 ThreadLocalInfo 的,參考代碼如下:

#ifdef _MSC_VER
__declspec(selectany) __declspec(thread) ThreadLocalInfo gCurrentThreadInfo;
#else
EXTERN_C __thread ThreadLocalInfo gCurrentThreadInfo;
#endif

struct ThreadLocalInfo
{
    Thread* m_pThread;
    AppDomain* m_pAppDomain; // This field is read only by the SOS plugin to get the AppDomain
    void** m_EETlsData; // ClrTlsInfo::data
};

上面的 m_pThread 就是 C# Thread 在 CLR 層面的承載,怎么去驗(yàn)證呢?可以把代碼跑起來,然后用 windbg 驗(yàn)證一下。

0:000> dt coreclr!gCurrentThreadInfo
   +0x000 m_pThread        : 0x000001e3`506c5fa0 Thread
   +0x008 m_pAppDomain     : 0x000001e3`506ba9b0 AppDomain
   +0x010 m_EETlsData      : 0x000001e3`506aa360  -> (null) 

0:000> !t
ThreadCount:      3
UnstartedThread:  0
BackgroundThread: 2
PendingThread:    0
DeadThread:       0
Hosted Runtime:   no
                                                                                                            Lock  
 DBG   ID     OSID ThreadOBJ           State GC Mode     GC Alloc Context                  Domain           Count Apt Exception
   0    1     2e04 000001E3506C5FA0    2a020 Preemptive  000001E3521DCE80:000001E3521DD4A8 000001e3506ba9b0 -00001 MTA 
   6    2     4ef8 000001E3506F1A30    21220 Preemptive  0000000000000000:0000000000000000 000001e3506ba9b0 -00001 Ukn (Finalizer) 
   7    3     3550 000001E3726A0AE0    2b220 Preemptive  0000000000000000:0000000000000000 000001e3506ba9b0 -00001 MTA

從卦中可以清楚的看到 m_pThread=0x000001e3506c5fa0 就是我們的主線程,最后的 num 就是放在與之關(guān)聯(lián)的 ThreadLocalModule 中,這個(gè)比較簡(jiǎn)單,關(guān)注下匯編代碼就好了,下面的 rax 就是 ThreadLocalModule。

00007ffb`218d2c2c 48b9b07b9921fb7f0000 mov rcx,7FFB21997BB0h
00007ffb`218d2c36 ba04000000      mov     edx,4
00007ffb`218d2c3b e8001fb55f      call    coreclr!JIT_GetSharedNonGCThreadStaticBase (00007ffb`81424b40)
00007ffb`218d2c40 8b4820          mov     ecx,dword ptr [rax+20h]
00007ffb`218d2c43 894dfc          mov     dword ptr [rbp-4],ecx

0:000> dp rax+0x20 L1
00000294`d0539790  abababab`0000000a

CLR層面用了太多的高層虛構(gòu)來玩了一套線程本地存儲(chǔ),其實(shí)最核心的還要理解再下一層的 __declspec(selectany) ,接下來聊聊這玩意是怎么玩的。

2. __declspec(selectany) 是怎么玩的

在Windows層面的術(shù)語中,有兩種 TLS 技術(shù)。

  • 動(dòng)態(tài)TLS

借助 Windows 提供的 TlsAlloc, TlsSetValue 之類的方法來實(shí)現(xiàn),并且存放在線程 _TEB.TlsSlots 的槽位中,參考代碼如下:

0:000> dt 0x000000f4f0ca6000 ntdll!_TEB
   +0x000 NtTib            : _NT_TIB
   ...
   +0x1480 TlsSlots         : [64] (null) 
   ...
  • 靜態(tài)TLS

C#的線程本地存儲(chǔ)用的就是靜態(tài)TLS,也就是在編譯時(shí)就已經(jīng)聲明好的,在 PE 文件里面有一個(gè) .tls 節(jié)點(diǎn),這個(gè)節(jié)點(diǎn)的數(shù)據(jù)會(huì)被每個(gè)線程在heap堆上copy一份,存放在 _TEB.ThreadLocalStoragePointer 來指向的指針數(shù)組中,參考代碼如下:

0:000> dt 0x000000f4f0ca6000 ntdll!_TEB
   +0x000 NtTib            : _NT_TIB
   +0x058 ThreadLocalStoragePointer : 0x00000294`d0536ab0 Void
   ...

動(dòng)態(tài)的TLS我就不介紹了,這里著重說一下靜態(tài)的TLS。

3. 靜態(tài)TLS詳解

為了方便講解,先上一段測(cè)試代碼。

#include <windows.h>
#include <stdio.h>
#include <limits.h>


__declspec(thread) int i = INT_MAX;
__declspec(thread) int j = INT_MAX;

int main() {
 int num1 = i;
 int num2 = j;
 printf("i=%d,j=%d", num1, num2);
}

上面的 i,j 值在編譯時(shí)就已經(jīng)放到了 PE 頭的 .tls 節(jié),可以用 PPEE 觀察下對(duì)象頭。

圖片

從卦中可以看到 .tls 占用了 0x400 字節(jié)大小,并且用 WinHex 真的觀察到了 i,j 的值,挺有意思。

在內(nèi)存中TLS區(qū)比這個(gè)還小一點(diǎn),可以觀察一下 DIRECTORY_ENTRY_TLS 節(jié)的 StartAddressOfRawData 和 EndAddressOfRawData 字段,這也是每個(gè)線程copy的原始內(nèi)存區(qū)域,可以看到只有 0x20D ,大概少了一半,截圖如下:

圖片

有了這些前置知識(shí),接下來觀察內(nèi)存中的地址,在運(yùn)行之前先把 ASLR 關(guān)掉,匯編代碼參考如下:

//int num1 = i;
   14 00411895 a1b4a14100      mov     eax,dword ptr [ConsoleApplication2!_tls_index (0041a1b4)]
   14 0041189a 648b0d2c000000  mov     ecx,dword ptr fs:[2Ch]
   14 004118a1 8b1481          mov     edx,dword ptr [ecx+eax*4]
   14 004118a4 8b8208010000    mov     eax,dword ptr [edx+108h]
   14 004118aa 8945f8          mov     dword ptr [ebp-8],eax

   //int num2 = j;
   15 004118ad a1b4a14100      mov     eax,dword ptr [ConsoleApplication2!_tls_index (0041a1b4)]
   15 004118b2 648b0d2c000000  mov     ecx,dword ptr fs:[2Ch]
   15 004118b9 8b1481          mov     edx,dword ptr [ecx+eax*4]
   15 004118bc 8b8204010000    mov     eax,dword ptr [edx+104h]
   15 004118c2 8945ec          mov     dword ptr [ebp-14h],eax

可以看到每一句大概會(huì)生成 5 行匯編代碼,我們簡(jiǎn)單分析下。

  • ConsoleApplication2!_tls_index (0041a1b4)

這個(gè)值就是 PE 頭的 AddressOfIndex 值,可以再回頭觀察下,里面存的就是 tls 索引,當(dāng)前是 0 ,參考如下:

0:000> dp 0041a1b4 L1
0041a1b4  00000000
  • fs:[2Ch]

在用戶態(tài)層面上 fs 指向的是當(dāng)前線程的 TEB 結(jié)構(gòu),其中的 2C 偏移指的就是 ThreadLocalStoragePointer 結(jié)構(gòu),windbg 觀察如下:

0:000> dg fs
                                  P Si Gr Pr Lo
Sel    Base     Limit     Type    l ze an es ng Flags
---- -------- -------- ---------- - -- -- -- -- --------
0053 002bc000 00000fff Data RW Ac 3 Bg By P  Nl 000004f3

0:000> dt 0x002bc000 ntdll!_TEB
   +0x000 NtTib            : _NT_TIB
   +0x01c EnvironmentPointer : (null) 
   +0x020 ClientId         : _CLIENT_ID
   +0x028 ActiveRpcHandle  : (null) 
   +0x02c ThreadLocalStoragePointer : 0x00664400 Void
   ...
  • edx,dword ptr [ecx+eax*4]

這句匯編是一個(gè)數(shù)組操作,翻譯成 C 就是 ThreadLocalStoragePointer[tls]。

0:000> dp 0x00664400 L1
00664400  00664448

這里要提醒的是:上面的 00664448 所在的 heap 位置其實(shí)就是 PE 頭里的 StartAddressOfRawData~EndAddressOfRawData內(nèi)存區(qū)域的 copy,截圖如下:

圖片

  • eax,dword ptr [edx+108h]

這句話的意思就是在 數(shù)組元素1 這個(gè)結(jié)構(gòu)上偏移108的位置存放著我們的 num 值,用 windbg 觀察之后果然就是的。

0:000> dp 00664448+0x108 L1
00664550  7fffffff

三:總結(jié)

C# 屬于一種業(yè)務(wù)高層抽象的語言,它的很多底層被C++再次隔離了,想要理解本篇的TLS,還得需要往下一層一層的擊穿,作為C#程序員太難了。

責(zé)任編輯:武曉燕 來源: 一線碼農(nóng)聊技術(shù)
相關(guān)推薦

2023-09-22 17:36:37

2024-12-26 10:05:58

C#前臺(tái)線程

2022-11-09 08:05:15

JavaScriptsuper()

2024-08-26 14:46:57

2021-03-29 00:02:10

C#Attribute元素

2018-07-03 08:48:48

對(duì)象存儲(chǔ)塊存儲(chǔ)

2024-06-28 12:47:29

C#弱引用底層

2018-06-25 09:32:44

2018-05-16 08:58:04

用戶畫像存儲(chǔ)

2022-08-30 07:39:57

C++namespace隔離

2020-10-30 07:11:31

C 語言編程

2020-11-17 06:57:15

存儲(chǔ)互聯(lián)網(wǎng)用戶

2022-11-02 08:51:01

2023-12-07 07:26:04

2025-01-10 08:15:22

C#異步底層

2020-10-23 07:00:00

C++函數(shù)

2018-04-27 09:22:21

數(shù)據(jù)存儲(chǔ)技巧

2021-12-29 07:18:20

重構(gòu)工具資源

2023-07-06 13:56:14

微軟Skype

2020-09-08 06:54:29

Java Gradle語言
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

99蜜月精品久久91| 手机在线免费毛片| 国产私拍精品| 久久99久久99精品免视看婷婷 | 亚洲人成色777777老人头| 奇米亚洲欧美| 69堂精品视频| 无码专区aaaaaa免费视频| 国产九色在线| 国产.精品.日韩.另类.中文.在线.播放 | 国产精品美女久久久久久免费| 91香蕉视频在线播放| 美女av一区| 欧美精品色一区二区三区| 欧美综合激情| 精品国产无码AV| 日韩av在线播放中文字幕| 欧美xxxx14xxxxx性爽| 成人h动漫精品一区| 精品国产一区二区三区性色av| 偷拍一区二区三区四区| 18视频在线观看娇喘| japanese国产在线观看| 神马香蕉久久| 91精品国产福利在线观看| 97成人在线观看视频| 中文字幕中文字幕在线十八区| 久久精品一二三| 国产精品三区四区| 国产精品久久影视| 日韩激情在线观看| 91av视频在线免费观看| 久草视频手机在线| 人人狠狠综合久久亚洲婷婷| 欧美色图免费看| 日韩精品―中文字幕| 超碰免费公开在线| 国产精品日产欧美久久久久| 精选一区二区三区四区五区| 亚洲精品一区二区三区新线路| 蜜臀av一区二区三区| 日韩美女在线观看| 久久99精品波多结衣一区| 亚洲国产日韩欧美一区二区三区| 久久成人一区二区| 在线免费看av网站| 外国成人免费视频| 欧美电影免费提供在线观看| 久热精品在线播放| 电影亚洲一区| 91精品91久久久中77777| 欧美日韩在线高清| 凸凹人妻人人澡人人添| 99热99精品| 激情视频在线观看一区二区三区| 黄频网站在线观看| 高清不卡在线观看| 国产视频在线观看一区| 黄色一级大片在线免费看国产一| 国产福利精品一区二区| 91丨九色丨国产| 99国产精品99| 亚洲欧美日韩国产| 欧美一级高清免费播放| 神马久久久久久久| 青青草视频网站| 久热av在线| wwwwxxxxx欧美| 欧美久久久久久一卡四| 国产中文在线视频| 国产精品网站在线观看| 欧美日韩日本网| a天堂中文在线| 综合欧美亚洲日本| 人妻激情另类乱人伦人妻| 女同一区二区免费aⅴ| 亚洲一二三四区不卡| 国产精品久久..4399| 性欧美xxx69hd高清| 色嗨嗨av一区二区三区| 天天干天天玩天天操| 91精品视频一区二区| 日韩一区二区三区在线视频| 人妖粗暴刺激videos呻吟| 天堂一区二区三区四区| 亚洲色图25p| 欧美视频一区二区在线| 欧美 日韩 国产 一区| 久久人人看视频| 青青国产在线视频| 国产一二三精品| 国产伦精品一区二区三区| 欧美女子与性| 亚洲天堂免费看| 亚洲中文字幕无码av永久| 在线天堂资源| 91精品国产欧美一区二区成人 | 国产99久久久| 免费成人av在线| 不卡视频一区二区三区| 青梅竹马是消防员在线| 中文字幕一区二区三中文字幕| 欧美黑人在线观看| 日韩制服一区| 亚洲国产精品va在看黑人| 国产福利在线导航| 一本色道久久综合亚洲精品高清| 国产精品久久一区| 黄色av一区二区三区| 亚洲国产成人私人影院tom | 久久精品官网| 欧美成人精品三级在线观看| 日韩欧美大片在线观看| 久久精品国产99久久6| 2019日本中文字幕| 一本色道久久综合熟妇| 大陆成人av片| av成人在线电影| 黄色在线视频观看网站| 亚洲精品免费在线| 日本久久精品一区二区| 美女18一级毛片一品久道久久综合| 香港成人在线视频| 亚洲精品20p| 要久久电视剧全集免费| 欧美极品少妇xxxxⅹ裸体艺术| 91麻豆精品在线| 99精品欧美一区| 久久这里只有精品8| 国产欧美在线观看免费| 亚洲欧美在线一区二区| 国产成人在线观看网站| 国产精品一区二区黑丝| 亚洲精品久久区二区三区蜜桃臀| 中文在线8资源库| 精品黑人一区二区三区久久| 加勒比婷婷色综合久久| 欧美/亚洲一区| 国产日产欧美精品| 高清美女视频一区| 一本大道av一区二区在线播放| 黄色国产在线视频| 亚洲网站啪啪| 成人资源av| 性xxxx18| 午夜视黄欧洲亚洲| 精品无码av一区二区三区| 亚洲一区欧美| 亚洲影院高清在线| 成人免费网址| 欧美肥胖老妇做爰| 国精产品一区一区| 久久爱另类一区二区小说| 亚洲国产午夜伦理片大全在线观看网站 | 午夜视频一区在线观看| 北京富婆泄欲对白| 亚洲成人在线| 韩日午夜在线资源一区二区 | 国产精品黄色av| 国产三级在线| 欧美日韩午夜影院| 在线观看天堂av| 国产九色精品成人porny| 黄色网在线视频| 精品中国亚洲| 久久久人成影片一区二区三区观看| 亚洲国产精品久久久久久6q| 亚洲午夜视频在线| 999精品免费视频| 免费日韩视频| 亚洲高清视频一区| 亚洲影视资源| 久久露脸国产精品| 香蕉视频免费看| 91国偷自产一区二区三区观看| 日本成人午夜影院| 国产一区二区电影| 无码日本精品xxxxxxxxx| 美腿丝袜亚洲图片| 国产成人免费av| av在线之家电影网站| 在线不卡一区二区| 久久综合亚洲色hezyo国产| 96av麻豆蜜桃一区二区| 欧美三级理论片| 欧美日一区二区在线观看| 久久偷看各类wc女厕嘘嘘偷窃 | 91入口在线观看| 老司机深夜福利在线观看| 亚洲视频专区在线| 99久久久国产精品无码免费| 午夜av一区二区三区| 亚洲黄色免费视频| 国产成人精品免费视频网站| 男女午夜激情视频| **女人18毛片一区二区| 蜜桃网站成人| 日韩一区二区三区在线看| 午夜精品久久久久久久男人的天堂| 精品99又大又爽又硬少妇毛片| 欧美一区二区福利视频| 欧美videossex极品| 国产精品高潮呻吟| 人妻无码一区二区三区| 久久99国产精品免费网站| 奇米精品一区二区三区| 99久久精品费精品国产| 九色一区二区| 国产一区二区三区黄网站| 全球成人中文在线| 香蕉久久aⅴ一区二区三区| 国产一区二区三区精品久久久| 国产一级性生活| 欧美精品久久久久久久久久丰满| 欧美午夜电影网| 日本少妇性生活| 亚洲免费在线视频一区 二区| brazzers精品成人一区| 国产精品1区二区.| 超碰在线播放91| 蜜桃av综合| 免费毛片网站在线观看| 亚洲高清资源在线观看| 天天综合色天天综合色hd| 欧美国产极品| 成人蜜桃视频| 国产精品毛片无码| 国产精品免费一区豆花| 中国字幕a在线看韩国电影| 欧美激情xxxx| 在线免费观看a视频| 俺也去精品视频在线观看| 国内三级在线观看| 亚洲免费电影在线观看| 欧美 日韩 国产 成人 在线 91| 91.com视频| 97超碰中文字幕| 欧美日韩在线直播| 日本欧美www| 在线一区二区三区做爰视频网站| 好看的av在线| 欧美日韩中文字幕在线| 人人干人人干人人干| 亚洲福利视频一区| 国产无码精品在线播放| 亚洲成人精品一区| 日韩精品在线不卡| 欧美色videos| 韩国av中文字幕| 色综合 综合色| av资源免费观看| 国产欧美日韩精品一区二区免费| 91国产精品电影| 国产无遮挡裸体视频在线观看| 亚洲国产精品女人久久久| 性欧美8khd高清极品| 欧美xxxxxxxxx| 黄频在线免费观看| 精品国产乱码久久久久久影片| 精品国产999久久久免费| 日韩精品一区二区三区三区免费| 精品国产99久久久久久宅男i| 欧美一级黄色大片| 亚洲第一天堂影院| 亚洲韩国青草视频| 午夜影院免费视频| 亚洲久久久久久久久久久| 九色视频在线播放| 日韩视频免费在线| 成人video亚洲精品| 久久久久久91| 新片速递亚洲合集欧美合集| 国产精品91久久久| 欧美激情啪啪| 国产精品久久精品国产| 亚洲国产网址| 中文字幕在线亚洲精品| 国模一区二区三区| 日本精品免费在线观看| 麻豆精品一区二区三区| 少妇丰满尤物大尺度写真| 99九九99九九九视频精品| 手机看片福利视频| 亚洲欧美电影一区二区| 青青草成人av| 欧美日韩一区二区在线观看 | 亚洲国产123| 亚洲综合另类小说| 日本视频免费观看| 日韩一区二区免费在线电影| 亚洲aⅴ乱码精品成人区| 中文字幕亚洲在线| 天天综合网在线观看| 爱高潮www亚洲精品| 96sao精品视频在线观看| 国产精品xxx在线观看| 欧美日产一区二区三区在线观看| 久久婷婷蜜乳一本欲蜜臀| 人人妻人人做人人爽| 午夜一级在线看亚洲| 伊人成人222| 91丝袜高跟美女视频| 国产wwwwxxxx| 精品久久久久久久久中文字幕 | a级大胆欧美人体大胆666| 国产成人在线精品| 91精品国产自产在线丝袜啪 | 18免费在线视频| 欧美国产在线电影| 男人亚洲天堂| 免费影院在线观看一区| 欧美国产激情| 超碰超碰在线观看| 97se亚洲国产综合在线| 国产va在线播放| 91久久线看在观草草青青 | 亚洲免费视频在线观看| 色婷婷av在线| 91久久久精品| 成人一区二区| 欧美三级午夜理伦三级| 成人午夜视频免费看| 日本一级特级毛片视频| 在线视频国产一区| 少妇的滋味中文字幕bd| 国产精品九九| www.久久久久久久久久久| 久久午夜羞羞影院免费观看| 国产中文字幕免费| 91精品久久久久久蜜臀| eeuss影院www在线观看| 国产精品777| 久久99视频| 日本www在线播放| caoporn国产一区二区| 精品欧美一区二区久久久久| 8x福利精品第一导航| 最新97超碰在线| 国产精品久久久久久久久久小说| 中文字幕中文字幕精品| 欧美日韩黄色一级片| 成人高清av在线| 国产一级大片在线观看| 欧美刺激午夜性久久久久久久| 国产在线二区| 91视频国产高清| 91精品国产麻豆国产在线观看| 岛国av在线免费| 国产精品久久久久久福利一牛影视 | 岛国精品视频在线播放| 亚洲欧美综合一区二区| 91国产一区在线| 牲欧美videos精品| 久久久久久久片| 国产精品美女一区二区| 国产精品国产精品国产专区| 久久久国产91| 日韩成人在线看| 日韩极品视频在线观看| 成人国产一区二区三区精品| 黄色片视频网站| 亚洲男人7777| 成人黄色免费观看| 久久av秘一区二区三区| 国产成人免费视频| 91香蕉在线视频| 国产一区二区三区在线看| 欧美日韩卡一| 污污污污污污www网站免费| 福利一区福利二区| 欧美不卡视频在线观看| 亚洲男人第一网站| 国产精品久久久久久吹潮| 欧美性受黑人性爽| 成人午夜私人影院| 在线观看你懂的网站| 久久亚洲私人国产精品va| 久久久久国产精品无码免费看| 岛国av一区二区三区| а天堂8中文最新版在线官网| 国产日韩精品在线播放| 亚洲午夜av| av黄色在线免费观看| 亚洲人成网站色在线观看| www国产在线| 欧美综合在线观看| 99九九热只有国产精品| 亚洲色图欧美另类| 日本乱人伦aⅴ精品| 自拍亚洲图区| 欧美综合激情| 国产大陆a不卡| 亚洲欧美偷拍一区| 久久精品国产一区| 亚洲国产合集| 性生活在线视频| 色94色欧美sute亚洲线路一ni| 精品自拍一区| 欧洲亚洲一区| 福利电影一区二区|