仿windows线程切换,添加模拟线程挂起与恢复代码
一、仿windows线程切换源代码:
ThreadCore.cpp :
#include "stdafx.h" #include <windows.h> #include <stdlib.h> #include "ThreadCore.h" #define _SELF "TLSN_仿windows线程切换" //------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------ int CurrentThreadIndex = 0; GMThread_t GMThreadList[MAXGMTHREAD] = {NULL,0}; #define GMTHREADSTACKSIZE 0x80000 void *WindowsStackLimit = NULL; //---------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------- __declspec(naked) void SwitchContext(GMThread_t *OldGMThreadp, GMThread_t *NewGMThreadp) { __asm { push ebp mov ebp,esp //sub esp,__local_size push edi push esi push ebx push ecx push edx push eax mov esi,OldGMThreadp mov edi,NewGMThreadp mov [esi + GMThread_t.KernelStack], esp //更改线程的堆栈,并存放在KernelStack中,上面一连串的push也是为了保存old线程的现场啊// //-------经典堆栈切换,另一个线程复活------------------------// mov esp,[edi + GMThread_t.KernelStack] pop eax pop edx pop ecx pop ebx pop esi pop edi //add esp,__local_size pop ebp ret //把esp中的值取出来给EIP,同时,esp + 4// } //pop完之后,正好执行线程入口函数// } void GMThreadStartup(GMThread_t *GMThreadp) { GMThreadp->func(GMThreadp->lpParameter); //执行线程函数// GMThreadp->Flags = GMTHREAD_EXIT; Scheduling(); return; } void IdleGMThread(void *lpParameter) { printf("IdleGMThread-------------------\n"); Scheduling(); return; } void PushStack(unsigned int **Stackpp, unsigned int v) { *Stackpp -= 1; **Stackpp = v; return; } void InitGMThread (GMThread_t *GMThreadp, char *name, void (*func)(void *lpParameter), void *lpParameter) { unsigned char *StackPages; unsigned int *StackDWORDParam; // 结构初始化赋值 GMThreadp->Flags = GMTHREAD_CREATE; GMThreadp->name = name; GMThreadp->func = func; GMThreadp->lpParameter = lpParameter; // 申请栈空间 StackPages = (unsigned char*)VirtualAlloc(NULL,GMTHREADSTACKSIZE, MEM_COMMIT, PAGE_READWRITE); // 清零 memset(StackPages,0,GMTHREADSTACKSIZE); // 堆栈初始化地址 GMThreadp->InitialStack = (StackPages + GMTHREADSTACKSIZE); // 堆栈限制 GMThreadp->StackLimit = StackPages; // 堆栈地址 StackDWORDParam = (unsigned int *)GMThreadp->InitialStack; // 入栈 PushStack(&StackDWORDParam, (unsigned int)GMThreadp); // 通过这个指针来找到:线程函数、函数参数//参数////相当于压入四字节的结构体指针地址// PushStack(&StackDWORDParam, (unsigned int)9); // 平衡堆栈 PushStack(&StackDWORDParam, (unsigned int)GMThreadStartup); // 线程入口函数,这个函数负责调用线程函数 PushStack(&StackDWORDParam, 5); // push ebp PushStack(&StackDWORDParam, 7); // push edi PushStack(&StackDWORDParam, 6); // push esi PushStack(&StackDWORDParam, 3); // push ebx PushStack(&StackDWORDParam, 2); // push ecx PushStack(&StackDWORDParam, 1); // push edx PushStack(&StackDWORDParam, 0); // push eax GMThreadp->KernelStack = StackDWORDParam; //压栈后的esp// GMThreadp->Flags = GMTHREAD_READY; return; } int RegisterGMThread(char *name, void (*func)(void *lpParameter), void *lpParameter) { int i; for (i = 1; GMThreadList[i].name; i++) { if (0 == stricmp(GMThreadList[i].name, name)) { break; } } InitGMThread(&GMThreadList[i], name, func, lpParameter); return (i | 0x55AA0000); } void Scheduling() { int i; int TickCount; GMThread_t *SrcGMThreadp; GMThread_t *NewGMThreadp; TickCount = GetTickCount(); SrcGMThreadp = &GMThreadList[CurrentThreadIndex]; NewGMThreadp = &GMThreadList[0]; for (i = 1; GMThreadList[i].name; i++) { if (GMThreadList[i].Flags & GMTHREAD_SLEEP)//if flag == GMTHREAD_SLEEP// { if (TickCount > GMThreadList[i].SleepMillisecondDot) { GMThreadList[i].Flags = GMTHREAD_READY; } } if (GMThreadList[i].Flags & GMTHREAD_READY) { NewGMThreadp = &GMThreadList[i]; break; } } CurrentThreadIndex = NewGMThreadp - GMThreadList; //下一次交换的old线程就是下标为CurrentThreadIndex的线程// SwitchContext(SrcGMThreadp, NewGMThreadp); //外平栈// return; } //-------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- void GMSleep(int Milliseconds) { GMThread_t *GMThreadp; GMThreadp = &GMThreadList[CurrentThreadIndex]; if ((GMThreadp->Flags) != 0) { GMThreadp->SleepMillisecondDot = GetTickCount() + Milliseconds; GMThreadp->Flags = GMTHREAD_SLEEP; } Scheduling(); return; } size_t Sustest; void GMSusThread() { GMThread_t *GMThreadp; GMThreadp = &GMThreadList[Sustest]; GMThreadp->Flags = 0; } size_t ResThread; void GMResumThread() { size_t orz = ResThread % 2; GMThread_t *GMThreadp; GMThreadp = &GMThreadList[ResThread / 2]; if(orz == 0) //查看要恢复成的状态// GMThreadp->Flags = 0x2; //准备// else GMThreadp->Flags = 0x8; //睡眠// } void vmmprint(char *f,int l,char *fmt,...) { int ret; char buffer[0x100]; va_list args; //------------------------------- va_start(args,fmt); _snprintf(buffer,0x80,"[%s]:",f,l); ret = _vsnprintf(buffer + strlen(buffer),0x100 - strlen(buffer),fmt,args); if(ret == -1) { strcpy(buffer,"vmmprint: error."); } //------------------------------- printf("%s",buffer); //OutputDebugString(buffer); return ; } void Thread1(void *lpParameter) //一共只被执行了三次// { int i; for (i = 0; i < 3; i++) { vmmprint(_SELF,__LINE__,"Thread1 \n"); GMSleep(1000); } return; } void Thread2(void *lpParameter) { int i = 0; for(;;) { vmmprint(_SELF,__LINE__,"Thread2 \n"); if(i==2) { Sustest = 3; GMSusThread(); printf("3线程已被挂起\n"); } if(i == 10) { ResThread = 6; GMResumThread(); printf("3线程已被恢复成ready状态\n"); } GMSleep(500); i++; } return; } void Thread3(void *lpParameter) { int i = 0; for(;;) { vmmprint(_SELF,__LINE__,"Thread3 \n"); GMSleep(800); } return; } void Thread4(void *lpParameter) { int i = 0; for (;;) { vmmprint(_SELF,__LINE__,"Thread4 \n"); GMSleep(200); } return; }
ThreadSwitch.cpp:
// ThreadSwitch.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "ThreadCore.h" #include <windows.h> extern int CurrentThreadindex; int main(int argc, char* argv[]) { //初始化线程环境// RegisterGMThread("Thread1",Thread1,NULL); RegisterGMThread("Thread2",Thread2,NULL); RegisterGMThread("Thread3",Thread3,NULL); RegisterGMThread("Thread4",Thread4,NULL); //模仿windows线程切换// for(;;) { Sleep(20); Scheduling(); } return 0; }
ThreadCore.h:
#if _MSC_VER > 1000 #pragma once #endif // #define MAXGMTHREAD 0x100 #define GMTHREAD_CREATE 0x01 #define GMTHREAD_READY 0x02 #define GMTHREAD_RUNNING 0x04 #define GMTHREAD_SLEEP 0x08 #define GMTHREAD_EXIT 0x100 // 线程结构体(仿THREAD) typedef struct { char *name; // 线程名,相当于线程TID int Flags; // 线程状态 int SleepMillisecondDot; // 休眠时间 void *InitialStack; // 线程堆栈起始位置 void *StackLimit; // 线程堆栈界限 void *KernelStack; // 线程堆栈当前位置,即ESP0 void *lpParameter; // 线程函数参数 void (*func)(void *lpParameter); // 线程函数 } GMThread_t; extern GMThread_t GMThreadList[MAXGMTHREAD]; void SwitchContext(GMThread_t *OldGMThreadp, GMThread_t *NewGMThreadp); void GMThreadStartup(GMThread_t *GMThreadp); void IdleGMThread(void *lpParameter); void PushStack(unsigned int **Stackpp, unsigned int v); void InitGMThread (GMThread_t *GMThreadp, char *name, void (*func)(void *lpParameter), void *lpParameter); int RegisterGMThread(char *name, void (*func)(void *lpParameter), void *lpParameter); void Scheduling(); void GMSleep(int Milliseconds); void Thread1(void *lpParameter); void Thread2(void *lpParameter); void Thread3(void *lpParameter); void Thread4(void *lpParameter);
二、读懂上面代码的话没什么难度,设个断点单步跟进很容易捋清楚
三、添加添加模拟线程挂起与恢复代码:
ps:这里我取了个巧(偷了个懒),构造挂起状态为flag =0...
ThreadCore.cpp:
#include "stdafx.h" #include <windows.h> #include <stdlib.h> #include "ThreadCore.h" #define _SELF "TLSN_仿windows线程切换" //------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------ int CurrentThreadIndex = 0; GMThread_t GMThreadList[MAXGMTHREAD] = {NULL,0}; #define GMTHREADSTACKSIZE 0x80000 void *WindowsStackLimit = NULL; //---------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------- __declspec(naked) void SwitchContext(GMThread_t *OldGMThreadp, GMThread_t *NewGMThreadp) { __asm { push ebp mov ebp,esp //sub esp,__local_size push edi push esi push ebx push ecx push edx push eax mov esi,OldGMThreadp mov edi,NewGMThreadp mov [esi + GMThread_t.KernelStack], esp //更改线程的堆栈,并存放在KernelStack中,上面一连串的push也是为了保存old线程的现场啊// //-------经典堆栈切换,另一个线程复活------------------------// mov esp,[edi + GMThread_t.KernelStack] pop eax pop edx pop ecx pop ebx pop esi pop edi //add esp,__local_size pop ebp ret //把esp中的值取出来给EIP,同时,esp + 4// } //pop完之后,正好执行线程入口函数// } void GMThreadStartup(GMThread_t *GMThreadp) { GMThreadp->func(GMThreadp->lpParameter); //执行线程函数// GMThreadp->Flags = GMTHREAD_EXIT; Scheduling(); return; } void IdleGMThread(void *lpParameter) { printf("IdleGMThread-------------------\n"); Scheduling(); return; } void PushStack(unsigned int **Stackpp, unsigned int v) { *Stackpp -= 1; **Stackpp = v; return; } void InitGMThread (GMThread_t *GMThreadp, char *name, void (*func)(void *lpParameter), void *lpParameter) { unsigned char *StackPages; unsigned int *StackDWORDParam; // 结构初始化赋值 GMThreadp->Flags = GMTHREAD_CREATE; GMThreadp->name = name; GMThreadp->func = func; GMThreadp->lpParameter = lpParameter; // 申请栈空间 StackPages = (unsigned char*)VirtualAlloc(NULL,GMTHREADSTACKSIZE, MEM_COMMIT, PAGE_READWRITE); // 清零 memset(StackPages,0,GMTHREADSTACKSIZE); // 堆栈初始化地址 GMThreadp->InitialStack = (StackPages + GMTHREADSTACKSIZE); // 堆栈限制 GMThreadp->StackLimit = StackPages; // 堆栈地址 StackDWORDParam = (unsigned int *)GMThreadp->InitialStack; // 入栈 PushStack(&StackDWORDParam, (unsigned int)GMThreadp); // 通过这个指针来找到:线程函数、函数参数//参数////相当于压入四字节的结构体指针地址// PushStack(&StackDWORDParam, (unsigned int)9); // 平衡堆栈 PushStack(&StackDWORDParam, (unsigned int)GMThreadStartup); // 线程入口函数,这个函数负责调用线程函数 PushStack(&StackDWORDParam, 5); // push ebp PushStack(&StackDWORDParam, 7); // push edi PushStack(&StackDWORDParam, 6); // push esi PushStack(&StackDWORDParam, 3); // push ebx PushStack(&StackDWORDParam, 2); // push ecx PushStack(&StackDWORDParam, 1); // push edx PushStack(&StackDWORDParam, 0); // push eax GMThreadp->KernelStack = StackDWORDParam; //压栈后的esp// GMThreadp->Flags = GMTHREAD_READY; return; } int RegisterGMThread(char *name, void (*func)(void *lpParameter), void *lpParameter) { int i; for (i = 1; GMThreadList[i].name; i++) { if (0 == stricmp(GMThreadList[i].name, name)) { break; } } InitGMThread(&GMThreadList[i], name, func, lpParameter); return (i | 0x55AA0000); } void Scheduling() { int i; int TickCount; GMThread_t *SrcGMThreadp; GMThread_t *NewGMThreadp; TickCount = GetTickCount(); SrcGMThreadp = &GMThreadList[CurrentThreadIndex]; NewGMThreadp = &GMThreadList[0]; for (i = 1; GMThreadList[i].name; i++) { if (GMThreadList[i].Flags & GMTHREAD_SLEEP)//if flag == GMTHREAD_SLEEP// { if (TickCount > GMThreadList[i].SleepMillisecondDot) { GMThreadList[i].Flags = GMTHREAD_READY; } } if (GMThreadList[i].Flags & GMTHREAD_READY) { NewGMThreadp = &GMThreadList[i]; break; } } CurrentThreadIndex = NewGMThreadp - GMThreadList; //下一次交换的old线程就是下标为CurrentThreadIndex的线程// SwitchContext(SrcGMThreadp, NewGMThreadp); //外平栈// return; } //-------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- void GMSleep(int Milliseconds) { GMThread_t *GMThreadp; GMThreadp = &GMThreadList[CurrentThreadIndex]; if ((GMThreadp->Flags) != 0) { GMThreadp->SleepMillisecondDot = GetTickCount() + Milliseconds; GMThreadp->Flags = GMTHREAD_SLEEP; } Scheduling(); return; } size_t Sustest; void GMSusThread() { GMThread_t *GMThreadp; GMThreadp = &GMThreadList[Sustest]; GMThreadp->Flags = 0; } size_t ResThread; void GMResumThread() { size_t orz = ResThread % 2; GMThread_t *GMThreadp; GMThreadp = &GMThreadList[ResThread / 2]; if(orz == 0) //查看要恢复成的状态// GMThreadp->Flags = 0x2; //准备// else GMThreadp->Flags = 0x8; //睡眠// } void vmmprint(char *f,int l,char *fmt,...) { int ret; char buffer[0x100]; va_list args; //------------------------------- va_start(args,fmt); _snprintf(buffer,0x80,"[%s]:",f,l); ret = _vsnprintf(buffer + strlen(buffer),0x100 - strlen(buffer),fmt,args); if(ret == -1) { strcpy(buffer,"vmmprint: error."); } //------------------------------- printf("%s",buffer); //OutputDebugString(buffer); return ; } void Thread1(void *lpParameter) //一共只被执行了三次// { int i; for (i = 0; i < 3; i++) { vmmprint(_SELF,__LINE__,"Thread1 \n"); GMSleep(1000); } return; } void Thread2(void *lpParameter) { int i = 0; for(;;) { vmmprint(_SELF,__LINE__,"Thread2 \n"); if(i==2) { Sustest = 3; GMSusThread(); printf("3线程已被挂起\n"); } if(i == 10) { ResThread = 6; GMResumThread(); printf("3线程已被恢复成ready状态\n"); } GMSleep(500); i++; } return; } void Thread3(void *lpParameter) { int i = 0; for(;;) { vmmprint(_SELF,__LINE__,"Thread3 \n"); GMSleep(800); } return; } void Thread4(void *lpParameter) { int i = 0; for (;;) { vmmprint(_SELF,__LINE__,"Thread4 \n"); GMSleep(200); } return; }
四、
__EOF__

本文作者:_TLSN
本文链接:https://www.cnblogs.com/lordtianqiyi/articles/15659277.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/lordtianqiyi/articles/15659277.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现