分类: LINUX
2010-06-09 17:51:21
TLS即Thread Local Storage。支持TLS的线程有三种类型的变量:线程局部变量,线程本地变量(TLS)和全局变量。TLS的不同之处:所有线程以同一个变量名或索引访问TLS变量,但不同线程的TLS变量存储在不同的内存区域。简而言之,就是同一个名字,不同的存储。
例如,有TLS变量errno,每个线程执行相同的语句“errno=i;”,errno在不同线程下有了不同的值。注意,这并不是在每一个线程中都声明一个名为errno的变量。这正是TLS的便利之处pthread_getspecific() pthread_setspecific()
2)特定语言的扩展
在gcc中,__thread int i;指定i为TLS变量
POSIX接口由线程库提供TLS支持
语言扩展则需要编译、链接工具提供TLS支持,例如
Bionic实现了关于TLS的POSIX接口,这些接口函数体系结构无关的部分定义在pthread.c文件中。
Bionic TLS实现机制图
下面,结合上图说明各个接口函数的使用。
Bionic支持最多64个key
Key Map:进程级变量,所有线程可见。该结构包含64个key的bitmap,记录所有key的使用情况
TLS and Stack:观察pthread.c中pthread_create()函数发现,每个线程创建之前会调用calloc()函数在堆中申请一块区域, 将tls指针指向 区域最高地址-64*sizeof(tls单元)。然后将tls作为childstack传给clone系统调用。Clone系统调用childstack用于为新创建的线程指定私有栈。由于栈向低地址增长,如果在用户态能获得tls指针,向高地址寻址可得tls数据。
pthread_key_create()
查Key Map返回一个整数类型的未使用的key的索引
pthread_getspecific() /pthread_setspecific()
参数为 index 和 val,即将索引为index的TLS变量值设为val。
其实现通过 ((unsigned *)(__get_tls())[index]), 其中__get_tls()返回TLS数组的指针。即创建线程时传入的tls指针。