|
转:http://blog.csdn.net/whatday/article/details/8781640
线程局部存储,Part 1:概述
线程局部存储,Part 2:显式TLS
线程局部存储,Part 3:编译器和链接器对隐式TLS的支持
线程局部存储,Part 4:访问__declspec(thread)变量
线程局部存储,Part 5:加载器对__declspec(thread)变量的支持(进程初始化阶段)
线程局部存储,Part 6:Windows Server 2003中隐式TLS支持方法设计中的问题
线程局部存储,Part 1:概述
和其它主流多线程操作系统一样,Windows为大家提供一个机制,该机制允许程序员实现基于线程的局部状态存储。这种能力通常称为线程局部存储(Thread Local Storage,TLS),这对于那些需要保存线程相关信息但需要全局可见的应用场景非常有用。
尽管TLS的介绍有很好的文档可参考,但关于其实现细节的介绍并不多(尽管也有一些非官方文档进行比较表面的介绍)。
至少从高层来将,TLS在概念上并不复杂。常规设计是将所有对TLS的访问都通过TEB中的指针来进行间接访问,TEB为操作系统定义的每个线程一份的数据结构,用于保存一些线程相关的信息。
TEB相对有比较多的文档介绍,为了对用户透明,一般使用一个段寄存器(X86上使用fs,X64上使用gs)指向当前线程的TEB地址。这样通过fs:[0x0](gs:[0x0] X64)将始终访问当前线程的TEB结构。TEB实际可以不出现在进程的平坦地址空间当中(TEB有一个域存放本身的平坦线性地址_TEB._NT_TIB.Self),但是这里段机制仅仅用来提供快速访问TEB结构,从而不需要搜索线程ID来确定TEB的地址(或其它相对较慢的机制来查找线程对应的TEB地址)。(%我猜作者这里想表达的意思是TEB并不需要在平坦地址空间中出现,所以想通过线性地址访问TEB会出错%)
在非X86和非X64架构中,访问TEB的底层机制是不同的,但是通常也是使用寄存器存放TEB的地址,从而使其更易于访问。
TEB本身可算是Windows中文档化最好的未公开结构,这主要是因为在最近构建的ntdll和ntoskrnl中该结构为调试器提供了一些类型信息(type information)。通过这些信息和一点反汇编工作,即可很容易的理解TLS的背后的实现细di:+9l9kb&ioy/cy.h!aykf9.+z+9oeyh!b!acyaykf9c.`&k!a oyfj9/o"iyb!acU9eN[OH
LK
LK
LJNY[Z[N\X[\NM[KZZY9.g:/oyfj9al9o#"zg :/oyaiQ9fd9b-. 9.*(iydyyl,y+b:/oyfj9k)9y.#y+i)l9nd#:/c9d"9/g9ey :)z/*:f9o#[OH
LK
LK
LJNY[Z[N\X[\NM[KZZY:/%y"zg :/oyaiy/oXXXY
yc9`:`(9$9d#9i)+.+yal*9"zg :/oyaiY9.+y/o9o#idba9c)[OH
LK
LK
LJNY[Z[N\X[\NM[KZZY9o9#/. iy"zg :/oyaiy/of9o#9`9a9e&z+:fc8/*e9.)zad9b-.H[YOHWS[OH
LKLML\H[H[YOHWS[OH
LKLML\H[XXXY
Oc9/o [OH
LK
LK
LJNY[Z[N\X[\NM[KZZY9nn:/9+\yb:/oyfj9/o. 9.*e /-yaj9/oXXXY
yc9b:/oyfj9+"zg 9b:/oQ9/o9o#/a+9k#y` o9ky)N |