Windows Internals 笔记——线程局部存储区
1.由于C/C++运行库是在多线程应用程序出现的许多年前设计的,因此运行库中的大多数函数是为单线程应用程序设计的。
2.当应用程序第一次调用_tcstok_s的时候该函数将传入的字符串地址保存在它自己的静态变量中,当我们后来再传入NULL的时候,该函数会去引用保存下来的字符串地址。多线程情况下一个线程可能会覆盖另一个线程的静态变量,为了解决这个问题,C/C++ 运行库使用了TLS。
int main()
{
char strToken[] = "A BC,DE\\FGH";
const char strDelimit[] = " ,\\"; char *context = nullptr;
char *next_context = nullptr; context = strtok_s(strToken, strDelimit, &next_context); while (context != nullptr)
{
std::cout << context << std::endl;
context = strtok_s(nullptr, strDelimit, &next_context);
} getchar();
return ;
}
3.系统中的每个进程都有一组正在使用标志,每个标志可以被设为FREE或INUSE,表示该TLS元素是否正在使用。Microsoft保证至少有TLS_MINIMUN_AVAILABLE个标志可供使用。再WinNT.h中被定义为64,系统在需要的时候分配更多的TLS元素,最多可达1000多个!
动态TLS
1.DWORD TlsAlloc(); 这个函数让系统对进程中的位标志进行检索并找到一个FREE标志。然后系统会将该标志从FREE改为INUSE并返回该标志在数组中的索引,并且这个索引无论是进程中当前正在运行的线程,还是今后可能会创建的线程都不能再使用。TlsAlloc在返回之前,会遍历进程中的每个线程,并根据新分配的索引,在每个线程的数组中把对应的元素设为0。如果没有,则返回TLS_OUT_OF_INDEXES(0xFFFFFFFF)。
2.当系统创建一个线程的时候,会分配TLS_MINIMUM_AVAILABLE个PVOID值,将它们都初始化为0,并与线程关联起来,每个线程都有自己的PVOID数组,数组中的每个PVOID可以保存任意值。
3.BOOL TlsSetValue(DWORD dwTlsIndex, PVOID pvTlsValue); 把一个值放到线程的数组中,但是它无法修改另一个线程的TLS值。为了使得函数运行得尽可能快,牺牲了错误检查,即使传入得索引值不是由TlsAlloc分配得到的。
4.PVOID TlsGetValue(DWORD dwTlsIndex);只会查看属于调用线程得数组。
5.BOOL TlsFree(DWORD dwTlsIndex); 函数会将进程内的标志位数组中对应的INUSE标志重新设回FREE,还会将所有线程中该元素的内容设为0。
6.通常,如果DLL要使用TLS,会在DLL_PROCESS_ATTACH的时候调用TlsAlloc,在DLL_PROCESS_DETACH的时候调用TlsFree。
静态TLS
__declspec(thread) DWORD gt_dwStartTime;
1. __declspec(thread) 告诉编译器应该在可执行文件或DLL文件中,把对应的变量放到它自己的段中。__declspec(thread)后面的变量必须被声明为全局变量或静态变量。
2.当编译器对程序进行编译的时候,会将所有TLS变量放到它们自己的段中,这个段名为.tls。链接岂会将所有对象模块中的.tls段合并成一个大的.tls段,并将它保存到生成的可执行文件或DLL文件中。
3.当系统将应用程序载入到内存的时候,会查看可执行文件中的.tls段,并分配一块足够大的内存来保存所有的静态TLS变量。每当应用程序中的代码引用到这些变量之一时,相应的引用会被解析到刚分配的这块内存中的一个位置。
4.如果进程创建了另一个线程,那么系统会获知这一情况并自动分配另一块内存来保存新线程的静态TLS变量,新线程只能访问自己的静态TLS变量。
5.当系统载入应用程序的时候,会首先确定应用程序的.tls段的大小,并将它与应用程序链接的所有DLL的.tls段的大小相加。当系统在创建线程的时候,会自动分配一块足够大的内存来保存应用程序和所有隐式链接的DLL需要的TLS变量。
Windows Internals 笔记——线程局部存储区的更多相关文章
- Windows Internals 笔记——线程
1.进程有两个组成部分,一个进程内核对象和一个地址空间.线程也有两个组成部分: 一个是线程的内核对象,操作系统用它管理线程.系统还用内核对象来存放线程统计信息的地方. 一个线程栈,用于维护线程执行时所 ...
- Windows Internals 笔记——线程优先级
1.每个线程都被赋予0(最低)~31(最高)的优先级数.当系统确定给哪个线程分配CPU时,它会首先查看优先级为31的线程,并以循环的方式进行调度.如果有优先级为31的线程可供调度,那么系统就会将CPU ...
- Windows Internals 笔记——关联性
1.默认情况下,Windows Vista在给线程分配处理器时,使用软关联.意思是如果其他因素都一样,系统将使线程在上一次运行的处理器上运行.让线程始终在同一个处理器上运行有助于重用仍在处理器高速缓存 ...
- Windows Internals 笔记——错误处理
1.Windows函数检测到错误时,会使用一种名为“线程本地存储区”的机制将相应的错误代码与“主调线程”关联到一起.这种机制使得不同的线程能独立运行,不会出现相互干扰对方的错误代码的情况. 2.Get ...
- Windows Internals 笔记——线程调度
1.线程内核对象中的CONTEXT反应了线程上一次执行时CPU寄存器的状态.大约每隔20ms,Windows都会查看所有当前存在的线程内核对象.Windows在可调度的线程内核对象中选择一个,并将上次 ...
- Windows Internals 笔记——CreateProcess
1.一个线程调用CreateProcess时,系统将创建一个进程内核对象,其初始使用计数为1.然后系统为新进程的主线程创建一个线程内核对象(使其计数为1). 2.CreateProcess在进程完全初 ...
- Windows Internals 笔记——进程
1.一般将进程定义成一个正在运行的程序的一个实例,由以下两部分构成: 一个内核对象,操作系统用它来管理进程,内核对象也是系统保存进程统计信息的地方. 一个地址空间,其中包含所有可执行文件或DLL模块的 ...
- Windows Internals 笔记——进程的权限
1.大多数用户都用一个管理员账户来登录Windows,在Vista之前,这样的登录会创建一个安全令牌.每当有代码试图使用一个受保护的安全资源时,操作系统就会出示这个令牌.从包括Windows资源管理器 ...
- Windows Internals 笔记——作业
1.Windows提供了一个作业内核对象,它允许我们将进程组合在一起并创建一个“沙箱”来限制进程能够做什么.创建只包含一个进程的作业同样非常有用,因为这样可以对进程施加平时不能施加的限制. 2.如果进 ...
随机推荐
- Django学习手册 - Form 插件
""" 核心: from django import formsfrom django.forms import fieldsfrom django.forms impo ...
- Javascript - ExtJs - 整合百度文章编辑器
ExtJs - 整合百度文章编辑器(ExtJs UEditor) 第一步:去官网下载最新版本的UEditor,UEditor下载. 第二步:在编辑器根目录创建一个Extjs-Editor.js,录入以 ...
- Oracle 服务器运行健康状况监控利器 Spotlight on Oracle 的安装与使用
1.使用教程;https://blog.csdn.net/defonds/article/details/52936664 2.下载链接:https://pan.baidu.com/s/1cn7tE_ ...
- google 开源项目阅读计划
1. glog 2. gflags 3. carto 4. ...
- AD7729_双通道Sigma-Delta ADC
sigma-delta adc的原理,就是通过一种结构把量化噪声调制到频谱的高端,也即对量化噪声而言,sdm是一个高通滤波器,而对基带信号则等价为一个全通滤波器,这样等价的基带信号的量化噪声就很小了, ...
- Linux中目录proc/net/dev详解【转】
转自:https://blog.csdn.net/yzy1103203312/article/details/77848192 版权声明:本文为博主原创文章,未经博主允许不得转载. https://b ...
- 【windows下进程searchfilterhost.exe分析】
searchfilterhost.exe [进程信息] 进程文件: searchfilterhost.exe 进程名称: n/a 英文描述: searchfilterhost.exe is a pro ...
- keepalived 的某台vip连接不通【原创】
keepalived 的某台vip连接不通,vip可以漂移到这台服务器,但是ping vip不通,telnet vip 3306服务也不通,但是telnet 服务器真实物理IP 3306是通的. 切换 ...
- Threading.local
在多线程环境下,每个线程都有自己的数据.一个线程使用自己的局部变量比使用全局变量好,因为局部变量只有线程自己能看见,不会影响其他线程,而全局变量的修改必须加锁. Threading.local可以创建 ...
- 关于centos7和centos6中平滑升级nginx到新版本v1.12.1修复nginx最新漏洞CVE-2017-7529的解决方案
关于centos7和centos6中平滑升级nginx到新版本v1.12.1修复CVE-2017-7529漏洞的解决方案 漏洞描述 2017年7月11日,Nginx官方发布最新的安全公告,在Nginx ...