1.动态tls介绍
windows为每个进程分配一组线程本地存储的标记. 至少有64个标记,如果程序使用超过了64个将动态增长.
这些标记有2种状态: free和inuse. 所有标记的状态对该进程中所有线程都是可见的.
程序中每个线程会对应每个标记一个slot,这个slot是个lpvoid的值
程序通过调用DWORD TlsAlloc(void) 来获取一个free状态的索引,并遍历该进程所有线程对其slot赋值为0,然后每个线程就可以通过
这个标记值(该标记的索引dword),来对自己的slot赋值,索引是每个线程可见的,但是每个线程自己的slot是只有自己可见的,这个slot就可以
理解为线程本地存储.
每个线程可以通过下面的函数对自己的slot赋值:
BOOL
WINAPI
TlsSetValue(
_In_ DWORD dwTlsIndex, //标记的索引值
_In_opt_ LPVOID lpTlsValue //给slot赋的值
)
或者获取slot的值:
LPVOID //返回slot的值
WINAPI
TlsGetValue(
_In_ DWORD dwTlsIndex //标记的索引值
)
所以一般用slot来存储指针
前面说过,标记对所有线程可见,如果有任何线程通过下面函数来释放标记,那么所有线程的对应于该标记的slot值将不可用
BOOL
WINAPI
TlsFree(
_In_ DWORD dwTlsIndex //标记的索引值
)
2.测试代码
DWORD threadProc(LPVOID param) { DWORD index = *(DWORD*)param; printf("tls1 [%d] value is %s\n", index, (char*)TlsGetValue(index)); TlsSetValue(index, "thread"); printf("tls2 [%d] value is %s\n", index, (char*)TlsGetValue(index)); return 0; } int main() { DWORD index; index=TlsAlloc(); TlsSetValue(index, "tls"); printf("main1 tls value is %s\n", (char*)TlsGetValue(index)); CreateThread(0, 0, (LPTHREAD_START_ROUTINE)threadProc, &index, 0, 0); Sleep(100); printf("main2 tls value is %s\n", (char*)TlsGetValue(index)); DWORD ret = TlsFree(index); system("pause"); return 0; }
执行结果:
main1 tls value is tls tls1 [1] value is (null) tls2 [1] value is thread main2 tls value is tls 请按任意键继续. . .
3.tls回调函数及静态TLS
tls回调函数会在线程创建和销毁时执行,因此可以用于反调试和软件加密解密
使用链接指令:#pragma comment(linker,"/include:__tls_used") 开启tls节
通过#pragma data_seg(".CRT$XLX")将回调函数填入tls节区中
#pragma data_seg(".CRT$XLX")
PIMAGE_TLS_CALLBACK callbacks[] = { callback1 ,callback2 ,0 };
#pragma data_seg()
回调函数原型:
void NTAPI callback1(PVOID hmodule, DWORD reason, PVOID reserved);
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp
· Vite CVE-2025-30208 安全漏洞
· 《HelloGitHub》第 108 期
· MQ 如何保证数据一致性?
· 一个基于 .NET 开源免费的异地组网和内网穿透工具