线程局部存储TLS, Thread Local Storage

TLS是C/C++运行库的一部分,而非操作系统的一部分。

分为动态TSL 和 静态TLS

一、动态TLS

应用程序通过调用一组4个函数来使用动态TLS, 这些函数实际上最为DLL所使用。

系统中的每个进程都有一组 正在使用标志(in-use flag), 每个标志可被设置为FREE 或者 INUSE, 表示该TLS元素是否正在使用。

微软平台保证至少有TLS_MINUMUM_AVALIABLE个标志位可供使用, TLS_MINUMUM_AVALIABLE在WinNT.h中被定义为64. 系统会在需要的时候分配更多的TLS元素,最多可达1000多个。

下面介绍下函数

DWORD    TlsAlloc();

这个函数让系统对进程中中的标志位进行检索并找到一个FREE标志,然后将该元素的标志从FREE置为INUSE, 并让TlsAlloc返回该元素的索引(下标)。

一个DLL(或应用程序)通常会将此索引保存在一个全局变量中,在整个进程范围内访问。

如果找不到一个标志为FREE的元素,则函数返回TLS_OUT_OF_INDEXES(在WinBase.h中被定义为0XFFFFFFFF)。

每个线程都有一个PVOID数组,每个线程使用每次TlsAlloc成功时的返回值作为各自线程中该数组的索引。

注意:该函数返回时会将每个线程中的数组对应的索引位置元素清零!

返回值:

失败:TLS_OUT_OF_INDEXES

成功:其他

BOOL    TlsSetValue(

DWORD   dwTlsIndex,   // TlsAlloc()函数的返回值

PVOID      pvTlsValue    //要设置的值

);

返回值:

TRUE: 成功

FALSE:失败

该函数的主调线程只能更改自己的数组,而不能修改其他线程的数组。

PVOID   TlsGetValue(

DWORD  dwTlsIndex    //TlsAlloc()函数的返回值

);

BOOL     TlsFree(

DWORD   dwTlsIndex    //TlsAlloc()函数的返回值

);

将该标志置为FREE, 并且将元素值清零。

二、静态TLS

__declspec(thread)   int  g_value = 0;

__declspec(thread)前缀是微软为VC++编译器增加的一个修饰符,它告诉编译器应该在可执行文件或DLL中,把对应的变量放到他自己的段中。

__declspec(thread)后面的变量必须声明为 全局变量 或 静态变量(全局或局部都可), 不可以将局部变量声明为__desclspec(thread)类型。

当编译器对程序进行编译的时候,会将所有TLS变量放到他自己的段中,这个段为.tls段。 链接器会将所有对象模块中的.tls段合并成一个大的.tls段,并将他保存到生成的exe或DLL文件中。

当系统将应用程序载入到内存的时候,会查看可执行文件中的.tls段,并分配一块足够的的内存来保存所有的静态TLS变量。 每当应用程序中的代码引用到这些变量之一事,相应的引用会被解析到刚分配的这块内存中的一个位置。 因此编译器必须生成额外的代码来引用静态TLS。

如果进程创建了一个新的线程,那么系统会得知这一情况并自动分配另一块内存来保存新线程的静态TLS变量。

当隐式加载DLL的时候:

如果exe使用了静态TLS, DLL也使用了TSL, 系统会首先确定exe的.tls段的大小,并将exe所有链接到的DLL的.tls段的大小相加。当系统在创建新线程的时候,会自动分配一块足够大的内存来保证应用程序和所有隐式链接的DLL需要的TLS变量。

当显式加载DLL的时候:

某DLL包含了静态TLS变量, exe使用LoadLibrary来显式加载DLL。 系统查看进程中已有线程,然后根据DLL中的TLS段扩大每个线程的TLS内存块。

当调用FreeLibrary释放DLL时,则该进程中的所有线程的TLS内存块也应该相应的缩减,缩减的部分是DLL中的TLS的部分。

【windows核心编程】线程局部存储TLS的更多相关文章

  1. windows核心编程 - 线程同步机制

    线程同步机制 常用的线程同步机制有很多种,主要分为用户模式和内核对象两类:其中 用户模式包括:原子操作.关键代码段 内核对象包括:时间内核对象(Event).等待定时器内核对象(WaitableTim ...

  2. windows核心编程 - 线程基础

    一.基本概念: 一个进程至少需要一个线程. 组成:一个线程包括仅包括一个线程堆栈和一个线程内核对象 线程堆栈:用于维护线程在执行代码时需要的所有函数参数和局部变量 线程内核对象:操作系统用它来对线程实 ...

  3. Windows核心编程&线程

    1. 线程上下文:线程内核对象保存线程上一次执行时的CPU寄存器状态 2. 线程上下文切换 3. windows操作系统为抢占式多线程操作系统,系统可以在任何时刻停止一个线程而另行调度另外一个线程.我 ...

  4. windows核心编程---第八章 使用内核对象进行线程同步

    使用内核对象进行线程同步. 前面我们介绍了用户模式下线程同步的几种方式.在用户模式下进行线程同步的最大好处就是速度非常快.因此当需要使用线程同步时用户模式下的线程同步是首选. 但是用户模式下的线程同步 ...

  5. 【windows核心编程】 第八章 用户模式下的线程同步

    Windows核心编程 第八章 用户模式下的线程同步 1. 线程之间通信发生在以下两种情况: ①    需要让多个线程同时访问一个共享资源,同时不能破坏资源的完整性 ②    一个线程需要通知其他线程 ...

  6. 【windows核心编程】 第六章 线程基础

    Windows核心编程 第六章 线程基础 欢迎转载 转载请注明出处:http://www.cnblogs.com/cuish/p/3145214.html 1. 线程的组成 ①    一个是线程的内核 ...

  7. Windows核心编程学习九:利用内核对象进行线程同步

    注:源码为学习<Windows核心编程>的一些尝试,非原创.若能有助于一二访客,幸甚. 1.程序框架 #include "Queue.h" #include <t ...

  8. 《windows核心编程系列》十九谈谈使用远程线程来注入DLL。

    windows内的各个进程有各自的地址空间.它们相互独立互不干扰保证了系统的安全性.但是windows也为调试器或是其他工具设计了一些函数,这些函数可以让一个进程对另一个进程进行操作.虽然他们是为调试 ...

  9. 用户模式下的线程同步的分析(Windows核心编程)

    线程同步 同一进程或者同一线程可以生成许多不同的子线程来完成规定的任务,但是多个线程同时运行的情况下可能需要对某个资源进行读写访问,比如以下这个情况:创建两个线程对同一资源进行访问,最后打印出这个资源 ...

随机推荐

  1. SQLite操作(C# )

    C#连接SQLite的...方法 http://www.cnblogs.com/virusswb/archive/2010/09/17/SQLite1.html 1 SQLite简介 SQLite,是 ...

  2. 使用CAShapeLayer与UIBezierPath画出想要的图形

    使用CAShapeLayer与UIBezierPath可以实现不在view的drawRect方法中就画出一些想要的图形 步骤: 1.新建UIBezierPath对象bezierPath 2.新建CAS ...

  3. iOS 开发--开源图片处理圆角

    概述 开源项目名称:HYBImageCliped 当前版本:2.0.0 项目用途:可给任意继承UIView的控件添加任意多个圆角.可根据颜色生成图片且可带任意个圆角.给UIButton设置不同状态下的 ...

  4. QSS的作用需要正确设置文件编码才能起作用

    QT这个库,无非使用OO对跨平台做了绝佳的封装,这其中的主要工作也就是比较繁琐而已,但并不多么了不起.唯独其中提供的QSS功能,让我感到十分神奇,做出来的效果实在很惊艳,而使用代码却又是如此简单,而且 ...

  5. mac root用户初始密码设置

    具体方法如下: 1)sudo su切换到root,输入的用户密码是当前用户的密码: 2)切换到root后,执行passwd root,设置root用户密码即可.

  6. linux jdk bin安装

    1.jdk-1_5_0_06-linux-i586.bin下载到/usr/soft,赋予可执行权限:chmod 755jdk-1_5_0_06-linux-i586.bin 2.执行:./jdk-1_ ...

  7. 【问题】和NULL比较遇到的问题

    1.问题描述: select FName from teacher where FId not in( select distinct FTeacherId from student ) 子查询返回的 ...

  8. 无法生成临时类(result=1)。 error CS0229: “DCSoftDotfuscate.aam.a”与“DCSoftDotfuscate.aam.a()”之间存在二义性

    对于错误无法生成临时类(result=1).error CS0229: “DCSoftDotfuscate.aam.a”与“DCSoftDotfuscate.aam.a()”之间存在二义性 出现这个错 ...

  9. BZOJ 2301 Problem b(莫比乌斯函数)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2301 题意:每次给出a,b,c,d,K.求有多少数对(x,y)满足a<=x< ...

  10. Java语言基本语法

    Java语言基本语法 一.标识符和关键字 标识符 在java语言中,用来标志类名.对象名.变量名.方法名.类型名.数组名.包名的有效字符序列,称为“标识符”: 标识符由字母.数字.下划线.美元符号组成 ...