TLS--线程局部存储

 

转自:https://blog.csdn.net/u013761036/article/details/54960277

这个东西并不陌生了,之前写过了一个关于这个的应用,利用静态TLS姿势实现代码段静态加密免杀或者所谓的加壳思路。地址在这:http://blog.csdn.net/u013761036/article/details/53967943今天就简单的整理下TLS的相关概念和常规应用。一开始说了一大堆的Windows的进程与线程啥啥啥的概念和原理,这里直接省略。

什么是线程局部存储?

    线程局部存储(Thread Local Storage,TLS)很好的解决了多线程设计中变量同步问题,比如你写一个exe里面有N个线程,你可以放弃使用TLS,因为你对自己设计的程序有比较全面的把握。你清楚自己设计的进程里总共有多少个线程,每个线程使用了哪些数据结构,内存空间申请、释放都在你的掌控之下,全局变量的访问全部都采用了同步技术,那是没问题的。如果你是一个DLL开发者,你无法确定调用这个DLL的素质程序里到底有多少个线程,每个线程的数据是如何定义的,这时,可以考虑使用线程据存储技术。

 

TLS分为静态和动态两种:

动态TLS,主要是使用这几个API TlsAlloc ,TlsGetValue,TlsSetValue,TlsFree

下面是微软MSDN上的一个例子,看下理解下:

 

 

[cpp] view plain copy

  1. <code class="language-cpp">#include <windows.h>   
  2. #include <stdio.h>   
  3.    
  4. #define THREADCOUNT 4   
  5. DWORD dwTlsIndex;   
  6.    
  7. VOID ErrorExit(LPSTR);   
  8.    
  9. VOID CommonFunc(VOID)   
  10. {   
  11.    LPVOID lpvData;   
  12.    
  13. // Retrieve a data pointer for the current thread.   
  14.    
  15.    lpvData = TlsGetValue(dwTlsIndex);   
  16.    if ((lpvData == 0) && (GetLastError() != ERROR_SUCCESS))   
  17.       ErrorExit("TlsGetValue error");   
  18.    
  19. // Use the data stored for the current thread.   
  20.    
  21.    printf("common: thread %d: lpvData=%lx\n",   
  22.       GetCurrentThreadId(), lpvData);   
  23.    
  24.    Sleep(5000);   
  25. }   
  26.    
  27. DWORD WINAPI ThreadFunc(VOID)   
  28. {   
  29.    LPVOID lpvData;   
  30.    
  31. // Initialize the TLS index for this thread.   
  32.    
  33.    lpvData = (LPVOID) LocalAlloc(LPTR, 256);   
  34.    if (! TlsSetValue(dwTlsIndex, lpvData))   
  35.       ErrorExit("TlsSetValue error");   
  36.    
  37.    printf("thread %d: lpvData=%lx\n", GetCurrentThreadId(), lpvData);   
  38.    
  39.    CommonFunc();   
  40.    
  41. // Release the dynamic memory before the thread returns.   
  42.    
  43.    lpvData = TlsGetValue(dwTlsIndex);   
  44.    if (lpvData != 0)   
  45.       LocalFree((HLOCAL) lpvData);   
  46.    
  47.    return 0;   
  48. }   
  49.    
  50. int main(VOID)   
  51. {   
  52.    DWORD IDThread;   
  53.    HANDLE hThread[THREADCOUNT];   
  54.    int i;   
  55.    
  56. // Allocate a TLS index.   
  57.    
  58.    if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)   
  59.       ErrorExit("TlsAlloc failed");   
  60.    
  61. // Create multiple threads.   
  62.    
  63.    for (i = 0; i < THREADCOUNT; i++)   
  64.    {   
  65.       hThread[i] = CreateThread(NULL, // default security attributes   
  66.          0,                           // use default stack size   
  67.          (LPTHREAD_START_ROUTINE) ThreadFunc, // thread function   
  68.          NULL,                    // no thread function argument   
  69.          0,                       // use default creation flags   
  70.          &IDThread);              // returns thread identifier   
  71.    
  72.    // Check the return value for success.   
  73.       if (hThread[i] == NULL)   
  74.          ErrorExit("CreateThread error\n");   
  75.    }   
  76.    
  77.    for (i = 0; i < THREADCOUNT; i++)   
  78.       WaitForSingleObject(hThread[i], INFINITE);   
  79.    
  80.    TlsFree(dwTlsIndex);  
  81.   
  82.    return 0;   
  83. }   
  84.    
  85. VOID ErrorExit (LPSTR lpszMessage)   
  86. {   
  87.    fprintf(stderr, "%s\n", lpszMessage);   
  88.    ExitProcess(0);   
  89. }</code>  


 

 

 

静态TLS

    静态线程局部存储是操作系统提供的另外一种线程与数据绑定的技术。它与动态TLS的区别在于,通过静态线程局部存储指定的数据无需使用专门的API函数,随意在易用性上会更好一些。

    静态线程局部存储预先将变量定义在PE文件内部,一般使用.tls节存储,对于相关API的调用由操作系统来完成。这种方式的有点就是从高级语言程序员角度来看更简单了。这种实现方式使得TLS数据的定义与初始化就像程序中使用普通的静态变量那样。

    对静态TLS变量的定义不需要想动态线程局部存储一样,调用相关API,只需要做如下声明即可:

_declspec(thread) int tlsFlag=1;

     为了支持这种编程模式。PE中的.tls节会包含一下信息:

初始化数据

用于每个线程初始化和终止的回调函数

TLS索引

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/509193.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

向量内积(点乘)和外积(叉乘)概念及几何意义

向量的内积&#xff08;点乘&#xff09; 定义 概括地说&#xff0c;向量的内积&#xff08;点乘/数量积&#xff09;。对两个向量执行点乘运算&#xff0c;就是对这两个向量对应位一一相乘之后求和的操作&#xff0c;如下所示&#xff0c;对于向量a和向量b&#xff1a; a和b…

SVN分支/合并

转自&#xff1a;https://blog.csdn.net/e3002/article/details/21469437 先说说什么是branch。按照Subversion的说法&#xff0c;一个branch是某个development line&#xff08;通常是主线也即trunk&#xff09;的一个拷贝&#xff0c;见下图&#xff1a; branch存在的意义在…

prim算法 求最小生成树

最小生成树Prim算法理解 标签&#xff1a; Prim算法理解最小生成树Prim2014-08-16 18:49 18482人阅读 评论(5) 收藏 举报版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 MST&#xff08;Minimum Spanning Tree&#xff0c;最小生成树&#xff09;问…

poj 1836 Alignment

题目大意&#xff1a; 给定一排人的身高&#xff0c;求踢出最少的人可以使队列身高如下形状&#xff1a; Description In the army, a platoon is composed by n soldiers. During the morning inspection, the soldiers are aligned in a straight line in front of the capta…

2016杭州ccpc

Kingdom of Obsession 标签&#xff1a; 二分图最大匹配2016-10-29 16:23 51人阅读 评论(2) 收藏 举报分类&#xff1a;二分图和最大匹配&#xff08;2&#xff09; 版权声明&#xff1a;本文为棒&#xff08;xian&#xff09;棒&#xff08;yu&#xff09;博主原创文章&#x…

深入理解C语言的函数调用过程

本文主要从进程栈空间的层面复习一下C语言中函数调用的具体过程&#xff0c;以加深对一些基础知识的理解。 先看一个最简单的程序&#xff1a; 点击(此处)折叠或打开 /*test.c*/#include <stdio.h> int foo1(int m,int n,int p){ int x m n p; …

Unity3D打包后日志文件输出目录

Unity3D打包后日志文件输出目录&#xff0c;包括日志文件和崩溃时记录文件 C:\Users\Administrator\AppData\LocalLow\长沙迪迈科股份有限公司\镍矿探秘 其中"..\长沙迪迈科股份有限公司\镍矿探秘" 为unity的公司和产品设置

Unity3d LookAt参数说明

Unity3d LookAt参数说明 //// 摘要: // Rotates the transform so the forward vector points at targets current position.//// 参数: // target:// Object to point towards.//// worldUp:// Vector specifying the upward direction.public void LookAt(…

初入职场的你不应错过的一些书籍

在职场中&#xff0c;听过最接地气的一句话就是&#xff1a;在职场中要眼睛里有活儿&#xff0c;知道什么该说什么不该说&#xff0c;也不要说自己不确定的事情。今天来推荐一些职场老手建议看的书 《好好说话》 有太多人初入职场不会说话&#xff0c;而说话的能力是可以培养的…

关于 Unity WebGL 的探索

转自:https://www.cnblogs.com/yaukey/p/unity_webgl_explore_1.html 查找了 Unity 的官方资料&#xff0c;我们如果需要使用 WebGL 需要面对以下几个挑战&#xff1a; Native Plugin&#xff1a;也就是说各种原生插件&#xff08;C/C等编译的本地机器码库&#xff09;&#…

Unity脚本生命周期与执行顺序

目录 脚本生命周期 MonoBehavior生命周期图脚本执行顺序 自定义执行顺序 (文章目录) 在Unity中&#xff0c;脚本可以理解为附加在游戏对象上的用于定义游戏对象行为的指令代码。必须绑定在游戏对象上才能开始它的生命周期。游戏对象可以理解为能容纳各种组件的容器&#xff0c…

Unity3D(UE4)加载倾斜摄影数据OSGB格式

在Unity3D平台动态加载调度倾斜摄影数据&#xff0c;利用多线程动态加载瓦片数据&#xff0c;可以顺畅加载海量的瓦片数据。目前测试可流畅加载100G左右数据&#xff0c;支持加载本地数据&#xff0c;数据可不放在Unity工程内&#xff0c;也可以将数据放置在服务器上实现网络加…

Unity打包失败解决方案

更改设置即可 &#xff1a;Edit -> Graphics Emulation-> Shader Hardware Tier 1

Unity3D实现谷歌数字地球

Unity3D实现谷歌地球 在Unity3d平台实现的类似谷歌地球的功能&#xff0c;可动态加载谷歌&#xff0c;ArcGis,BingMap,天地图影像&#xff0c;也可加载国界线等矢量文件以及在线加载高程文件。 视频链接: 地球操作:https://www.bilibili.com/video/BV1mT4y1P771 地球漫游:h…

Unity罗技方向盘接入

要想在Unity中接入罗技方向盘的数据&#xff0c;首先必须安装驱动&#xff0c;并且打开安装的软件&#xff0c;否则在Unity中会一直连接不成功。状态如下&#xff1a; 然后下载相应的开发包Logitech SDK即可&#xff0c;需要替换相应的LogitechSteeringWheelEnginesWrapper.dll…

sscanf

sscanf&#xff08;&#xff09; 2010-01-28 11:53:42| 分类&#xff1a; Work|举报|字号 订阅 下载LOFTER我的照片书 |定义函数 int sscanf (const char *str,const char * format,........); 函数说明 sscanf()会将参数str的字符串根据参数format字符串来转换并格…

字典树

微博:TankyWoo基新博客:TankyWooTanky Woo的前博客 字典树&#xff08;讲解模版&#xff09; 又称单词查找树&#xff0c;Trie树&#xff0c;是一种树形结构&#xff0c;是一种哈希树的变种。典型应用是用于统计&#xff0c;排序和保存大量的字符串&#xff08;但不仅限于字符串…

Unity3D谷歌地球

Unity3D实现谷歌地球 在Unity3d平台实现的类似谷歌地球的功能&#xff0c;可动态在线加载谷歌&#xff0c;ArcGis,BingMap,天地图等影像&#xff0c;也可加载国界线等矢量文件以及在线加载高程文件。 视频链接: 地球操作:https://www.bilibili.com/video/BV1mT4y1P771 地球…

线段树的操作

登录 | 注册 MetalSeed 思绪来得快去的也快&#xff0c;偶尔会在这里停留。 目录视图摘要视图订阅 移动信息安全的漏洞和逆向原理 程序员11月书讯&#xff0c;评论得书啦 Get IT技能知识库&#xff0c;50个领域一键直达数据结构专题——线段树 标签&#xff1a; …