对Tls了解的兄弟进来看看

fishly_0 2008-05-08 03:21:44
When a thread is created, an array of TLS_MINIMUM_AVAILABLE PVOID values is allocated, initialized to 0, and associated with the thread by the system. As Figure 21-1 shows, each thread gets its own array and each PVOID in the array can store any value.
当一个线程被创建出来,系统将会关联与该线程一个存放PVOID值的数组,每个线程都会有这样一个数组.

Before you can store information in a thread's PVOID array, you must know which index in the array is
available for use—this is what the earlier call to TlsAlloc is for. Conceptually, TlsAlloc reserves an index for you. If TlsAlloc returns index 3, it is effectively saying that index 3 is reserved for you in every thread currently executing in the process as well as in any threads that might be created in the future.
在我们往PVOID数组存放数据之前,我们必须首先调用TlsAlloc取得一个可用的PVOID数组成员的Index .如果TlsAlloc返回的Index是3,那么当前进程的所有线程的PVOID数组的 Index为3的成员都被保留(是否是:只要一个线程被分配了Index=3,那么其他线程的Index 3也就不能使用了,尽管各个线程的PVOID数组是不同的,如果是这样,那为什么要这么做呢?)

上面这两段是Windows核心编程里说的,不知道我理解对不对?

我创建了一个MFC工程进行了验证,用一个Button响应函数在主线程中 多次调用TlsAlloc,每次获得的索引号都不一样,是
依次递增的,这个还能解释,相当于每次都获得数组里一个新的空位来保存数据. 但是我创建了几个线程,在线程里面调用
TlsAlloc,我发现得到的Index是跟着主线程得到的Index递增的,即:主线程最后一次调用TlsAlloc得到的index是10的话,
那么新开的线程得到的一定是11, 这跟书上讲的不一样.经过这样的试验,我觉得是每个进程的所有线程共享一个 存放PVOID值的数组, 但感觉这样跟线程本地存储的概念不相符和,而且跟书上讲的也不一样.

以前一直没有仔细研究过TLS,现在很想把Tls弄明白了,还请知道的高手帮忙解答下^_^
...全文
120 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
fishly_0 2008-05-12
  • 打赏
  • 举报
回复
几天没来了,多谢各位的答复,我再好好研究研究^_^
wushigang 2008-05-09
  • 打赏
  • 举报
回复
理解起来不是那么困难吧。好好读一读,多头开始,好好理解线程本地存储的由来和意义。

每个线程的那100个PVOID是独立的,但任一线程分配到某个编号时,系统自动将其它线程的对应编号保留起来,这样才能将同一编号用做线程本地存储。
搞清楚线程本地存储,就是各个线程表面上都用同一个值,实际上这个值是独立的。


"每个进程的所有线程共享一个存放PVOID值的数组",这个理解是错的。

线程A的array[3]被reserved了,线程B的array[3]也会被reserved,而且所有线程的array[3]都被系统自动保留。不是因为共享才会被保留,而是系统指定要让他们一致。
比如若要每个线程维持一个lasterror,可以包装起来两上函数。如果不用STL的话,这两个函数是无法实现的。
void seterror(int err){array[3]=err;}
int getlasterror(){return arrary[3];}
哪个线程调用这两个函数,它用的就是哪个线程的array[3],从而达到每个线程都有独立的lasterror的目的。
zhoujianhei 2008-05-09
  • 打赏
  • 举报
回复
需要注意的是,MFC也使用TLS进行线程数据绑定,如果你要试验最好在WIN32下进行。
======================================================================
线程本地存储
要将数据(指针、句柄)绑定到线程,我们需要一个全局索引,而这个索引正是通过TlsAlloc分配的。
TlsAlloc
函数功能:分配一个线程局部存储(TLS)索引。该进程的任何线程都可以使用该索引来存储和检取线程中的值。
函数原型:DWORD TlsAlloc(void)
参数:无。
返回值:若函数成功,则返回值为一个TLS索引。失败则返回0XFFFFFFFF。
需要说明的是,进程可以同时分配多个索引,用于存放不同的数据。下面提供进程、线程、索引、存储槽的关系图以便更好地理解。
......

http://blog.csdn.net/zhoujianhei/archive/2007/11/19/1891891.aspx
Edward 2008-05-08
  • 打赏
  • 举报
回复
看来楼主断章取义了。。。你从头把那章读一下吧,有个图再加上作者的例子应该×非常×明白啊。
scq2099yt 2008-05-08
  • 打赏
  • 举报
回复
up
僵哥 2008-05-08
  • 打赏
  • 举报
回复
多读几遍,多加思考.也许可以明白的.首先,我觉得更重要的一点是了解Tls的作用,或者说其存在的目的,那样你才能更好地理解.
fishly_0 2008-05-08
  • 打赏
  • 举报
回复
To edyang:
按照字面上的意思,应该是如果TlsAlloc返回3,那么这个Index将会为当前执行的所有线程以及将来可能创建的线程保留.那意思就是这个Index 3 不可能在被其他线程所获得了,是这个意思吧? 但是书上不是所,每个线程都有一个这样的array,为什么线程A的array[3]被reserved了,线程B的array[3]也会被reserved呢? 除非是所有的线程共享一个array才需要这样做吧?
Edward 2008-05-08
  • 打赏
  • 举报
回复
建议你再仔细读一下这句:

If TlsAlloc returns index 3, it is effectively saying that index 3 is reserved for you in every thread currently executing in the process as well as in any threads that might be created in the future.
小麻侬 2008-05-08
  • 打赏
  • 举报
回复
gz

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧