windows核心编程---线程局部存储区

来源:互联网 发布:程序员会几种语言 编辑:程序博客网 时间:2024/05/18 11:15

-概述
1.窗口附加字节,通过使用SetWindowWord和SetWindowLong将数据与一个指定的窗口关联。
2.可使用线程局部存储区将数据与一个正在执行的线程关联。
3.C/C++运行库使用了TLS。
C/C++运行库的大多数函数最初设计时,没有考虑多线程。

-动态TSL
管理TLS的内部数据结构:
系统中的每个进程都有一组正在使用标志。
每个标志可被设为FREE或INUSE。

Microsoft保证至少有TLS_MINIMUM_AVAILABLE个位标志可供使用。

使用:
1.

DWORD TlsAlloc();

检索进程的位标志,找到一个FREE的。将该标志从FREE改为INUSE,让TlsAlloc返回该标志在位数组中的索引。

一个DLL或应用通常将这个索引,保存在一个全局变量中。无法找到一个FREE标志,返回TLS_OUT_OF_INDEXES。

系统创建一个线程时,会分配TLS_MINIMUM_AVAILABLE个PVOID值,
初始化为0,并与线程关联。
每个线程都有自己的PVOID数组。

进程内各线程共享一个索引区间。
2.

BOOL WINAPI TlsSetValue(  _In_     DWORD  dwTlsIndex,  _In_opt_ LPVOID lpTlsValue);

将一个值,放到调用线程的数组中。

从一个线程传数据到到另一个线程的唯一简单方法,是在调用CreateThread或_beginthreadex时,传一个值给它们。

3.从线程的数组中取回一个值

LPVOID WINAPI TlsGetValue(  _In_ DWORD dwTlsIndex);

5.释放索引

BOOL WINAPI TlsFree(  _In_ DWORD dwTlsIndex);

释放索引,同时会让调用线程此索引处PVOID设置为0.

-使用动态TLS
通常,DLL要使用TLS。
它会在DllMain处理DLL_PROCESS_ATTACH时调用TlsAlloc,在DllMain处理DLL_PROCESS_DETACH时调用TlsFree。
对TlsSetValue和TlsGetValue的调用最有可能发生在DLL所提供的其它函数中。

DWORD dwTlsIndex;PVOID pvSomeValue;...dwTlsIndex = TlsAlloc();TlsSetValue(dwTlsIndex, (PVOID)12345);TlsFree(dwTlsIndex);// TlsAlloc返回前,会遍历进程中的每个线程,并根据新分配的索引,在每个线程的数组中把对应的元素设为0dwTlsIndex = TlsAlloc();pvSomeValue = TlsGetValue(dwTlsIndex);

-使用静态TLS
不必在代码中调用任何函数。
假设想将应用创建的每个线程与该线程的启动时间关联。

__declspec(thread) DWORD gt_dwStartTime = 0;

__declspec(thread)属于Visual C++编译器的一个修饰符,告诉编译器在可执行文件或DLL文件中,把对应的变量放到它自己的段中。修饰,全局或静态变量。这个段名为.tls。

链接器会将所有对象模块中的.tls段合并成一个大的.tls段,并将它保存到生成的可执行文件或DLL文件中。

系统将应用载入到内存时,会查看可执行文件的.tls段,并分配足够大内存来保存所有静态TLS变量,每当应用的代码引用这些变量时,引用会被解析到刚分配这块内存中的一个位置。
如进程创建了另一个线程,那么系统会获知这一情况,并自动分配另一块内存来保存新线程的静态TLS变量。每个线程有一个内存块来保存静态TLS变量。所有线程此内存块大小相同。

阅读全文
0 0
原创粉丝点击