书上说进程内有一索引数组,其大小和该进程中创建的线程的数组大小一样,关于这两个数组,关系到底如何,谁能详细讲一下,我刚在学,还不是很清楚。如果能把TLS实现过程通俗的讲一下,就更好了,我到现在还不是很清楚TLS能用到哪里,有什么用?
解决方案 »
- vc++ 怎么让while死循环执行一定时间后退出?
- 串口发送调用writefile()出现死锁,不知道如何解决,贴出代码请大家看看
- 问个钩子的问题!!!!!!!!!!!!!!!!!!!!!!!!
- 讨论程序员的爱情模式!
- 在程序中想用一个表显示数据,还可以对该表进行编辑,请问用什么控件好?VC里可以用什么控件?
- 高分跪求基于内容的图象检索vc++源码!
- 怎么将double的转换成CString的?或者字符也行?
- =====高手来帮忙阿=====看看这个函数应该怎么写~~~
- windows中共享文件夹在注册表中的键值??
- 还是关于研华采集卡的,我先做软件采集再高速采集,这之间应该先closedevice再opendevice吧
- IE下ocx控件中的消息映射问题
- MFC初学子窗口的简单问题
Dispather header
Total user time
Total kernel time
...
---->TLS arrray
...
Thread environment block可见每个线程都有着单独的TLS。当线程生成时,系统保留并请空一列存储单元,至少64个,给这个个线程。进程也增加一个对该列单元的索引,索引中的每位(bit)对应每个单元,表示占用或空闲。
之所以需要另外一个索引表,是因为零值可以合法的放到存储单元中,系统需要用其他方法来表示单元是否被占用。如果有了第二个线程,进程就维护两个索引表。由此类推。当你要使用TLS时,首先要取得一个空的存储单元的号码,然后你就利用这个号码对TLS进行操作,直到你释放这个单元为止。有4个函数可以来操作TLS:DWORD TlsAlloc() // 取得一个存储单元
BOOL TlsSetValue(DWORD index, PVOID val) // 存一个指针或长整数
PVOID TlsGetValue(DWORD index) // 取
BoOL TlsFree(DWORD index) // 放弃一个存储单元
更详细的内容,你可以参考
1:"Thread Local Storage", http://msdn2.microsoft.com/en-us/library/ms686749.aspx
2:"Windows Internals", M. Russinovich and D. Solomon
“用于管理TLS的数据结构是很简单的,Windows仅为系统中的每一个进程维护一个位数组,再为该进程中的每一个线程申请一个同样长度的数组空间。TlsSetValue和TlsGetValue分别用于设置和取得线程数组中的特定成员的值,而它们使用的索引就是TlsAlloc函数的返回值。这就充分说明了进程中唯一的位数组和各线程数组的关系。例如,TlsAlloc返回3,那就说明索引3被此进程中的每一个正在运行的和以后要被创建的线程保存起来,用以访问各自线程数组中对应的成员的值。”我看书上讲得好像就一个位数组,没说有多个索引表啊?
1.位置在各线程当中形成一个对称性分派,但是需要注意的是,任意同进程内的线程的申请可以占用(保留)某一位置,同样的,任意同进程内的线程也可以释放该位置,这是其中一个注意点。
2.由于有限性,最多只有1088个,虽然可以达到多线程当中的快速有效的重复访问,但是却不可以滥用,在不非必要使用的时候尽可能不使用,除非使用之后可以解决相应的应用瓶颈。使用的时候尽量公开化,尽可能避开封装,否则会缩小该封装使用范围,特别是一些非单例类型当中避免使用。
3.由于单元空间的有限性,正如MSDN所说的那样,在已知的不破坏封装性的情况下尽可能使用一个扩展结构(存储其指针到线程局部存储当中)来替代多个线程局部存储空间位置的占用。
最近也在看TLS方面的内容,我把它理解成类对象,每个类对象只能有一个类的成员的拷贝。
2、系统使进程索引位数组的长度和每个线程存储数据的位数组长度一样,否则索引位数组如果有100位,而每个线程存储数组有101位,索引数组就没法索引这101位的数据并使用它,长度一样是管理上的需要;
3、进程的索引数组成员FREE和INUSE的设置是:比如一个新建进程,进程的索引数组a[n]成员值全部是FREE,而全部线程的线程存储数组成员都是空闲,出现某线程首次调用TlsAlloc函数时返回比如索引数组成员第一个a[0]就是FREE的索引,TlsAlloc函数将a[0]值改为 INUSE,该线程使用TlsSet函数将自己的线程存储数组b[0]的成员使用,在a[0]未被TlsFree函数释放前,所用线程的线程存储数组 b[0]都可以使用,不是一个线程用一次存储数组就必须要主线程调用一次TlsAlloc函数;
4、索引数组可以通过TlsFree函数释放索引(即改a[0]值为FREE)和b[0]空间,保证进程的索引数组不会全部被占用;
5、象很多内核对象一样"线程存储数组"和"索引数组"也是WINDOWS封闭保护的私处只一,不会让你象自己定义个数组那样直观、直接、明白的使用,而是提供几个TlsAlloc、TlsSetValue、TlsGetValue、TlsFree这样的函数间接使用,所以感觉有点暧昧难懂;
6、动态使用TLS的步骤:
(1)主线程调用TlsAlloc函数分配标记线程存储数组未被使用成员的索引A,并将进程索引位数组的该索引成员值由FREE改为INUSE;
(2)线程使用TlsAlloc函数分配的索引使用TlsSetValue(索引A,要设置的值)设置自己线程存储数组成员的值以便使用,或者用TlsGetValue函数读取成员值使用; (3)主线程调用TlsFree(索引A)释放索引A和存储数组空间,已保证索引和存储空间的循环使用;