-
-
[原创]线程本地存储TLS(Thread Local Storage)的原理和实现——实现探究
-
发表于: 2012-7-3 16:18 5708
-
本文为线程本地存储TLS系列之实现探究。
我们在上一篇线程本地存储TLS(Thread Local Storage)的原理和实现——分类和原理中曾经说过TLS可以分为两类:静态TLS和动态TLS。然后又分别说明了两者在程序实现时的用法,并且还说明了windows对这两类TLS的实现原理,我们本文的目的是从底层实现的角度深入探究,深刻理解原理。
先考虑以下两个问题:
1、在上一篇中,我们说到静态TLS数据是在编译时放入.tls节,然后在系统加载程序时,会去寻找.tls节,并且分配一个足够大的内存空间来存放所有这些静态TLS变量。那么问题是,当程序加载后,对静态TLS数据分配的内存空间在哪里呢?用什么来表示呢?
2、在上一篇中,我们说到动态TLS是存放在每一个线程独立的TLS slot数组中,这个数组的大小是TLS_MINIMUM_AVAILABLE维,那么这个数组在哪里呢?TlsSetValue和TlsGetValue应该就是访问的这个数组,在取得索引的情况下,如果我们知道这个数组的位置,那么我们是否完全就能抛开上面两个函数自己读写来测试呢?
一、线程环境块TEB
在给出具体程序之前,我们有必要先讨论一下线程环境块TEB。
我们知道,每个线程都有属于自己的一系列数据,这些数据就是通过TEB来管理,当然就包括像TLS这样的线程私有数据。那么TEB的结构是什么样的呢?在微软的文档和头文件上,我没有查到TEB完整的信息,不过我们还是可以通过Windbg得到的,以下是TEB的详细展开信息:
0:001> dt -b nt!_TEB ntdll!_TEB +0x000 NtTib : _NT_TIB +0x000 ExceptionList : Ptr32 +0x004 StackBase : Ptr32 +0x008 StackLimit : Ptr32 +0x00c SubSystemTib : Ptr32 +0x010 FiberData : Ptr32 +0x010 Version : Uint4B +0x014 ArbitraryUserPointer : Ptr32 +0x018 Self : Ptr32 +0x01c EnvironmentPointer : Ptr32 +0x020 ClientId : _CLIENT_ID +0x000 UniqueProcess : Ptr32 +0x004 UniqueThread : Ptr32 +0x028 ActiveRpcHandle : Ptr32 +0x02c ThreadLocalStoragePointer : Ptr32 +0x030 ProcessEnvironmentBlock : Ptr32 +0x034 LastErrorValue : Uint4B +0x038 CountOfOwnedCriticalSections : Uint4B +0x03c CsrClientThread : Ptr32 +0x040 Win32ThreadInfo : Ptr32 +0x044 User32Reserved : Uint4B +0x0ac UserReserved : Uint4B +0x0c0 WOW32Reserved : Ptr32 +0x0c4 CurrentLocale : Uint4B +0x0c8 FpSoftwareStatusRegister : Uint4B +0x0cc SystemReserved1 : Ptr32 +0x1a4 ExceptionCode : Int4B +0x1a8 ActivationContextStack : _ACTIVATION_CONTEXT_STACK +0x000 Flags : Uint4B +0x004 NextCookieSequenceNumber : Uint4B +0x008 ActiveFrame : Ptr32 +0x00c FrameListCache : _LIST_ENTRY +0x000 Flink : Ptr32 +0x004 Blink : Ptr32 +0x1bc SpareBytes1 : UChar +0x1d4 GdiTebBatch : _GDI_TEB_BATCH +0x000 Offset : Uint4B +0x004 HDC : Uint4B +0x008 Buffer : Uint4B +0x6b4 RealClientId : _CLIENT_ID +0x000 UniqueProcess : Ptr32 +0x004 UniqueThread : Ptr32 +0x6bc GdiCachedProcessHandle : Ptr32 +0x6c0 GdiClientPID : Uint4B +0x6c4 GdiClientTID : Uint4B +0x6c8 GdiThreadLocalInfo : Ptr32 +0x6cc Win32ClientInfo : Uint4B +0x7c4 glDispatchTable : Ptr32 +0xb68 glReserved1 : Uint4B +0xbdc glReserved2 : Ptr32 +0xbe0 glSectionInfo : Ptr32 +0xbe4 glSection : Ptr32 +0xbe8 glTable : Ptr32 +0xbec glCurrentRC : Ptr32 +0xbf0 glContext : Ptr32 +0xbf4 LastStatusValue : Uint4B +0xbf8 StaticUnicodeString : _UNICODE_STRING +0x000 Length : Uint2B +0x002 MaximumLength : Uint2B +0x004 Buffer : Ptr32 +0xc00 StaticUnicodeBuffer : Uint2B +0xe0c DeallocationStack : Ptr32 +0xe10 TlsSlots : Ptr32 +0xf10 TlsLinks : _LIST_ENTRY +0x000 Flink : Ptr32 +0x004 Blink : Ptr32 +0xf18 Vdm : Ptr32 +0xf1c ReservedForNtRpc : Ptr32 +0xf20 DbgSsReserved : Ptr32 +0xf28 HardErrorsAreDisabled : Uint4B +0xf2c Instrumentation : Ptr32 +0xf6c WinSockData : Ptr32 +0xf70 GdiBatchCount : Uint4B +0xf74 InDbgPrint : UChar +0xf75 FreeStackOnTermination : UChar +0xf76 HasFiberData : UChar +0xf77 IdealProcessor : UChar +0xf78 Spare3 : Uint4B +0xf7c ReservedForPerf : Ptr32 +0xf80 ReservedForOle : Ptr32 +0xf84 WaitingOnLoaderLock : Uint4B +0xf88 Wx86Thread : _Wx86ThreadState +0x000 CallBx86Eip : Ptr32 +0x004 DeallocationCpu : Ptr32 +0x008 UseKnownWx86Dll : UChar +0x009 OleStubInvoked : Char +0xf94 TlsExpansionSlots : Ptr32 +0xf98 ImpersonationLocale : Uint4B +0xf9c IsImpersonating : Uint4B +0xfa0 NlsCache : Ptr32 +0xfa4 pShimData : Ptr32 +0xfa8 HeapVirtualAffinity : Uint4B +0xfac CurrentTransactionHandle : Ptr32 +0xfb0 ActiveFrame : Ptr32 +0xfb4 SafeThunkCall : UChar +0xfb5 BooleanSpare : UChar
//通过windgb查看_TEB得到的我的系统(winXP+SP3)中的_TEB的实现 struct STEB { NT_TIB NtTib; PVOID EnvironmentPointer; //中间若干数据,与此处研究无关,故不展开,只标记偏移。下面的Reserved2,Reserved3也是同理 BYTE Reserved1[12]; PVOID ThreadLocalStoragePointer; //指向存放静态TLS数据的地址的指针的地址 BYTE Reserved2[3552]; PVOID TlsSlots[64]; //指向存放动态TLS数据的TLS Slot数组 BYTE Reserved3[132]; PVOID TlsExpansionSlots; //当索引大于63时,TlsSlots数组存不下了,就会新分配内存来存放,并且将指针记录在这里 //后面还有若干数据,与此处研究无关,故省略 };
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏记录
参与人
雪币
留言
时间
伟叔叔
为你点赞~
2024-5-31 05:13
心游尘世外
为你点赞~
2024-5-31 02:00
QinBeast
为你点赞~
2024-5-31 01:52
飘零丶
为你点赞~
2024-3-29 01:51
shinratensei
为你点赞~
2024-1-30 05:05
一笑人间万事
为你点赞~
2023-3-7 00:42
赞赏
他的文章
看原图
赞赏
雪币:
留言: