[笔记]Windows核心编程《二十一》线程本地存储器TLS

前言

引入用线程本地存储器TLS原因

由于运行期库是在多线程应用程序出现前的许多年前的设计的,因此运行期库中的大多数函数是用于单线程应用程序的。

例如strtok,在多线程环境中,一个线程可以调用 strtok,然后,在它能够再次调用该函数之前,另一个线程也可以调用strtok。在这种情况下,第二个线程会在第一个线程不知道的情况下,让strtok用一个新地址来改写它的静态变量。第一个线程将来调用strtok时将使用第二个线程的字符串,这就会导致各种各样难以发现和排除的错误。
这也叫不可重入函数,上次调用函数结果可能会影响这次调用结果.

为了解决这个问题,C / C + +运行期库使用了T L S。每个线程均被赋予它自己的字符串指针,供strtok函数使用。需要予以同样对待的其他C / C + +运行期库函数还有asctime和gmtime。

一、动态TLS

若要使用动态T L S,应用程序可以调用一组 4个函数。这些函数实际上是 D L L用得最多的函数。

windows用来管理TLS的内部数据结构:
在这里插入图片描述
每个标志均可设置为 F R E E或者I N U S E,表示T L S时隙( s l o t )是否正在使用。

TlsAlloc函数

若要使用动态T L S,首先必须调用T l s A l l o c函数:

DWORD TlsAlloc( );

这个函数命令系统对进程中的位标志进行扫描,并找出一个 F R E E标志。然后系统将该标志从FREE改为INUSE,并且TlsAlloc返回位数组中的标志的索引。

TlsSetValue函数

要将一个值放入线程的数组,可以调用TlsSetValue函数:

BO0L TlsSetValue(DWORD dwTlsIndex,PVOID pvTlsValue);

TlsGetValue函数

PVOID TlsGetValue(DWORD dwTlsIndex) ;

该函数返回的值将与索引 dwTlsIndex处的 T L S时隙联系起来。与 TlsSetValue一样,TlsGetValue只查看属于调用线程的数组。

TlsFree函数

当在所有线程中不再需要保留T L S时隙的位置的时候,

BOOL TlsFree(DWORD dwTlsIndex) ;

由进程的位标志数组管理的I N U S E标志再次被设置为F R E E。

使用动态T L S

通常情况下,如果 DLL使用TLS,那么当它用DLL_PROCESS_ATTACH标志调用它的DllMain函数时,它也调用TlsAlloc。当它用DLL_PROCESS_DETACH调用DllMain函数时,它就调用TlsFree。对TlsSetValue和TlsGetValue的调用很可能是在调用DLL中包含的函数时进行的。

二、静态TLS

你想要将起始时间与应用程序创建的每个线程联系起来。只需要将起始时间变量,声明为下面的形式:

__declspec(thread)DWORD gt_dwStartTime = 0;

当编译器对程序进行编译时,它将所有的TLS变量放入它们自己的节,这个节的名字是.tls。链接程序将来自所有对象模块的所有 .tls节组合起来,形成结果的可执行文件或 D L L文件中的一个大的.tls节。

缺点:

  1. 编译器必须生成一些辅助代码来引用该静态 T L S变量,这将使你的应用程序变得比较大而且运行的速度比较慢。在 x86 CPU上,将为每次引用的静态 T L S变量生成3个辅助机器指令。
  2. 系统允许包含静态 T L S变量的库在运行期进行显式加载,但是T L S数据没有进行相应的初始化。如果试图访问这些数据,就可能导致访问违规。

总结

1.动态TLS和静态TLS区别?

动态TLS:

  • 主要线程数据存放在内存中,加载dll时载入,卸载dll时释放。

静态TLS:

  • 主要线程数据存在dll文件的TLS节中,增加DLL大小。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二进制怪兽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值