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.如果进 ...
随机推荐
- python初级实战-----主机在线情况监控web
背景 公司有600多台服务器,打算写一个小程序,能一眼看见哪些服务器不在线. 大体思路是: 1.把所有服务器ip存进数据库,ping命令判断服务器是否在线 2.更新数据库中ip的状态 3.简单的web ...
- linux 安装matlab
转自: https://www.cnblogs.com/Amedeo/archive/2018/06/03/9129925.html 一.下载“Crack”和”ISO”文件 下载地址如下所示:http ...
- Linux就该这么学(1)-系统概述(学习笔记)
一.热门的Linux系统开源许可协议 GNU GPL(GNU General Public License,GNU 通用公共许可证) BSD(Berkeley Software Distributio ...
- Git使用手册【转】
转自:https://www.jianshu.com/p/e32a8e7ca93b 目录: Git是什么 基本概念 Git的诞生 Git的安装与配置 创建版本库 Git操作略览 远程仓库:git的杀招 ...
- Awk 命令学习总结、AWk命令系列学习(linux shell)
AWK基本语法 下面没有提到awk命令怎么使用了,你可以通过 运行:awk –h 查询到所有命令及参数!下面把awk作为一门语言分节介绍. linux awk 内置变量使用介绍 awk语言中,怎么 ...
- HTTP协议06-报文首部
HTTP报文格式 HTTP协议的请求和响应报文中必定包含HTTP首部.首部内容为客户端和服务器分别处理请求和响应提供所需要的信息. 1)HTTP请求报文 在请求中,HTTP报文由方法.URI.HT ...
- NO-CARRIER
自己动手写了创建虚拟接口,删除虚拟接口程序,频繁调用创建删除时,有时将接口up起来时会报错: Name not unique on network 利用ip link命令来查看接口(及其对应的索引) ...
- atoi 和 itoa的实现
atoi 和 itoa是面试笔试经常要考到的题目,下面两份代码是用C语言实现的atoi和itoa: 1, atoi 原型: int atoi(const char *nptr); 函数说明: 参数np ...
- 【原创】大叔经验分享(36)CM部署kafka
1 下载kafka parcel http://archive.cloudera.com/kafka/parcels/latest/KAFKA-3.1.1-1.3.1.1.p0.2-el7.parce ...
- Django 笔记(六)mysql增删改查
注:增删改查表数据在 views.py 内 添加表数据: 删表数据: 改表数据: 查表数据: 常用的查询方法: 常用的查询条件: 相当于SQL语句中的where语句后面的条件 语法:字段名__规则