Windows 下实现线程局部存储

以下叙述的仅是Windows NT,XP 等系统下实现线程局部存储的一个思路,并不是绝对的实现方法。

线程局部存储(Thread Local Storage,TLS),是多线程普及的情况下一个很有用的机制,该机制使得线程可以使用属于自己的全局变量。只需要在一个全局变量的定义前加上相应的关键字,即可指定一个全局变量为TLS属性的。

GCC:__thread int number;

Windows: __declspec(thread) int number;

在Windows 中,正常情况下一个全局变量或者静态变量会被放到 “.data”段或 ".bss"段中,但是当我们指定变量的属性为TLS时,编译器会将这些变量放在PE文件的 “.tls”段中。以下列出TLS变量的一些属性:

1.实际存储位置:

当启动一个线程时,会从进程的中分配出一段足够的大小的空间,把".tls"段的内存复制到这块空间中。保证每个线程有自己独立的".tls"副本。所以TLS属性的同一个变量,在不同线程中的地址是不一样的。

2.线程寻找TLS属性变量的方式:

每个线程都拥有一个线程环境块(Thread Environment Block,TEB),其存储该线程的一些线程信息,其中固定偏移处(0x2C)是一个TLS数组,该数组的大小是固定的,有64个DWARD大小,其中第一个元素存储的是指向该线程".tls"副本的地址,于是要得到一个变量的地址,需要再加上该变量在“.tls”段中的偏移即可。因此,通过TEB即可找到每一个专属TLS变量的位置,而 TEB 的位置则存储在 X86 的 FS 段寄存器中。

3.TLS变量的构造与析构:

在Window PE 文件的结构中有一个元素为 IMAGE_DERECT_ENTRY_TLS,这个元素保存的地址和长度就是 TLS 表的地址和长度,而TLS表中保存了所有TLS变量的构造函数和析构函数的地址,Windows系统就是根据TLS表中的内容,在每次线程启动或退出时对TLS变量进行构造和析构

4.关于TLS数组中存储的内容的疑问:

在《程序员自我修养》第354页描述中,说TLS数组的第一个元素存储的是该线程的 ".tls" 副本的地址,且该数组大小是64,但是没有说明剩余的63个元素里存储的是什么。

但网上所说的64个元素是指64个DWARD空间,其中每个元素可以存储句柄或者指针,用来执行私有对象的地址。我感觉个人没有很明白。。。希望以后自己再看的时候能想清楚!!!!!!!!???

参见博客:http://blog.chinaunix.net/uid-9589034-id-2401074.html

你可能感兴趣的:(Unix环境编程,编译链接)