Windows进程与线程学习笔记(五)—— 模拟线程切换
生活随笔
收集整理的這篇文章主要介紹了
Windows进程与线程学习笔记(五)—— 模拟线程切换
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Windows進(jìn)程與線程學(xué)習(xí)筆記(五)—— 模擬線程切換
- ThreadSwitch代碼分析
- ThreadSwitch.cpp
- ThreadCore.h
- ThreadCore.cpp
- 總結(jié)
ThreadSwitch代碼分析
ThreadSwitch.cpp
// ThreadSwitch.cpp : Defines the entry point for the console application. //#include "stdafx.h" #include "ThreadCore.h"int main(int argc, char* argv[]) {//初始化線程環(huán)境RegisterGMThread("Thread1",Thread1,NULL);RegisterGMThread("Thread2",Thread2,NULL);RegisterGMThread("Thread3",Thread3,NULL);RegisterGMThread("Thread4",Thread4,NULL);//仿Windows線程切換for (;;){Sleep(20);ThreadPolling();}return 0; }ThreadCore.h
// ThreadCore.h: interface for the ThreadCore class. // //#if !defined(AFX_THREADCORE_H__3C5DBE32_012F_4176_884F_8D9EA510122D__INCLUDED_) #define AFX_THREADCORE_H__3C5DBE32_012F_4176_884F_8D9EA510122D__INCLUDED_#if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000#define MAXGMTHREAD 0x100#define GMTHREAD_CREATE 0x01 #define GMTHREAD_READAY 0x02 #define GMTHREAD_RUNING 0x04 #define GMTHREAD_SLEEP 0x08 #define GMTHREAD_SUSPEND 0x10 #define GMTHREAD_EXIT 0x100typedef struct {char *name; // 線程名 相當(dāng)于線程TIDint Flags; // 線程狀態(tài)int SleepMillisecondDot; // 休眠時(shí)間void *InitialStack; // 線程堆棧起始位置,也就是EBPvoid *StackLimit; // 線程堆棧界限void *KernelStack; // 線程堆棧當(dāng)前位置,也就是ESPvoid *lpParameter; // 線程函數(shù)的參數(shù)void (*func)(void *lpParameter); // 線程函數(shù)} GMThread_t; //--------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------/* 線程結(jié)構(gòu)體數(shù)組* 線程在不同狀態(tài)的存儲(chǔ)位置不同* 正在運(yùn)行的線程位于KPCR* 等待中的線程位于等待鏈表* 就緒的線程位于調(diào)度鏈表中* 這里對(duì)于以上三種情況使用一個(gè)數(shù)組進(jìn)行包含* main函數(shù)也是一個(gè)線程,信息存在第一個(gè)數(shù)組成員里,也就是下標(biāo)為0的位置* 創(chuàng)建線程時(shí),是從下標(biāo)為1的位置開始分配的*/ extern GMThread_t GMThreadList[MAXGMTHREAD]; //--------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------void IdleGMThread(void *lpParameter);void GMThreadStartup(GMThread_t *GMThreadp); 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);void GMSleep(int Milliseconds);void ThreadPolling();void Thread1(void *lpParameter); void Thread2(void *lpParameter); void Thread3(void *lpParameter); void Thread4(void *lpParameter);#endif // !defined(AFX_THREADCORE_H__3C5DBE32_012F_4176_884F_8D9EA510122D__INCLUDED_)ThreadCore.cpp
#include "stdafx.h" #include "stdio.h" #include "windows.h"#include "ThreadCore.h"#define _SELF "滴水_仿Windows線程切換"//--------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------int CurrentThreadindex = 0; GMThread_t GMThreadList[MAXGMTHREAD] = { NULL,0 };#define GMTHREADSTACKSIZE 0x80000void *WindowsStackLimit = NULL;//--------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------__declspec(naked) void SwitchContext(GMThread_t *SrcGMThreadp,GMThread_t *DstGMThreadp) {__asm{//保存現(xiàn)場push ebpmov ebp,esp//sub esp,__LOCAL_SIZEpush edipush esipush ebxpush ecxpush edxpush eaxmov esi,SrcGMThreadp //當(dāng)前線程結(jié)構(gòu)體指針mov edi,DstGMThreadp //目標(biāo)線程結(jié)構(gòu)體指針// esi + GMThread_t.KernelStack == SrcGMThreadp.KernelStackmov [esi+GMThread_t.KernelStack], esp//---------------經(jīng)典堆棧切換 另一個(gè)線程復(fù)活----------------------------------// edi + GMThread_t.KernelStack == DstGMThreadp.KernelStackmov esp, [edi+GMThread_t.KernelStack]//此時(shí),ESP為目標(biāo)線程堆棧棧頂pop eaxpop edxpop ecxpop ebxpop esipop edi//add esp,__LOCAL_SIZEpop ebpret //ebp之后是GMThreadStartup函數(shù)地址} }//用來執(zhí)行線程函數(shù) void GMThreadStartup(GMThread_t *GMThreadp) {//執(zhí)行線程函數(shù)GMThreadp->func(GMThreadp->lpParameter);//線程函數(shù)執(zhí)行結(jié)束,設(shè)置線程狀態(tài)為EXITGMThreadp->Flags = GMTHREAD_EXIT;//線程切換Scheduling();return ; }void IdleGMThread(void *lpParameter) {Scheduling();return ; }void PushStack(unsigned int **Stackpp,unsigned int v) {// ESP 減去一個(gè)單位(4個(gè)字節(jié))*Stackpp -= 1;//[ESP] = 參數(shù)v**Stackpp = v;return ; }void initGMThread(GMThread_t *GMThreadp,char *name,void (*func)(void *lpParameter),void *lpParameter) {unsigned char *StackPages;unsigned int *StackDWORDParam;//結(jié)構(gòu)初始化賦值GMThreadp->Flags = GMTHREAD_CREATE; //初始化線程為創(chuàng)建狀態(tài)GMThreadp->name = name; //線程名GMThreadp->func = func; //線程函數(shù),已經(jīng)定義好GMThreadp->lpParameter = lpParameter; //參數(shù)//申請(qǐng)堆??臻gStackPages = (unsigned char*)VirtualAlloc(NULL,GMTHREADSTACKSIZE,MEM_COMMIT,PAGE_READWRITE);//堆棧清零memset(StackPages,0,GMTHREADSTACKSIZE);//堆棧棧底(EBP)GMThreadp->InitialStack = (StackPages+GMTHREADSTACKSIZE-0x10);//堆棧邊界地址GMThreadp->StackLimit = StackPages;StackDWORDParam = (unsigned int*)GMThreadp->InitialStack;//入棧PushStack(&StackDWORDParam,(unsigned int)GMThreadp); //線程結(jié)構(gòu)體自身指針,用來尋找 線程函數(shù)|函數(shù)參數(shù)PushStack(&StackDWORDParam,(unsigned int)9); //平衡堆棧PushStack(&StackDWORDParam,(unsigned int)GMThreadStartup); //函數(shù)地址,執(zhí)行線程函數(shù)的入口函數(shù)//下面的值可以隨便寫PushStack(&StackDWORDParam,5); //push ebpPushStack(&StackDWORDParam,7); //push ediPushStack(&StackDWORDParam,6); //push esiPushStack(&StackDWORDParam,3); //push ebxPushStack(&StackDWORDParam,2); //push ecxPushStack(&StackDWORDParam,1); //push edxPushStack(&StackDWORDParam,0); //push eax//執(zhí)行后,堆棧變化如下 GMThreadp->KernelStack = StackDWORDParam; //指向當(dāng)前線程的棧頂(ESP)GMThreadp->Flags = GMTHREAD_READAY; //線程狀態(tài)設(shè)置為就緒return ; }int RegisterGMThread(char *name,void (*func)(void *lpParameter),void *lpParameter) {int i;//為數(shù)組下標(biāo)為0的成員賦值,GM Thread,相當(dāng)于main函數(shù)線程if (GMThreadList[0].name==NULL){//申請(qǐng)堆棧初始化操作 線程數(shù)組 ,線程名字 ,函數(shù)地址 ,參數(shù)initGMThread(&GMThreadList[0], "IDLE GM Thread", IdleGMThread, NULL);}//新增的線程從下標(biāo)為1開始寫入for (i=1;GMThreadList[i].name;i++){//判斷數(shù)組中尚未初始化的成員if (0==stricmp(GMThreadList[i].name,name)){break;}}//初始化線程結(jié)構(gòu)體initGMThread(&GMThreadList[i],name,func,lpParameter);return (i|0x55AA0000); }void Scheduling(void) {int i;int TickCount;GMThread_t *SrcGMThreadp;GMThread_t *DstGMThreadp;TickCount = GetTickCount();SrcGMThreadp = &GMThreadList[CurrentThreadindex]; //當(dāng)前線程結(jié)構(gòu)體指針DstGMThreadp = &GMThreadList[0]; //目標(biāo)線程結(jié)構(gòu)體指針//遍歷線程數(shù)組,找到狀態(tài)為就緒的線程for (i=1;GMThreadList[i].name;i++){if (GMThreadList[i].Flags&GMTHREAD_SLEEP){if (TickCount>GMThreadList[i].SleepMillisecondDot){GMThreadList[i].Flags = GMTHREAD_READAY;}}if ((GMThreadList[i].Flags&GMTHREAD_READAY)){//檢測到有線程的狀態(tài)為就緒,將其作為目標(biāo)線程DstGMThreadp = &GMThreadList[i];break;}}CurrentThreadindex = DstGMThreadp-GMThreadList; //得到即將執(zhí)行的線程下標(biāo)SwitchContext(SrcGMThreadp,DstGMThreadp); //線程切換return ; }//--------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------void GMSleep(int Milliseconds) {GMThread_t *GMThreadp;GMThreadp = &GMThreadList[CurrentThreadindex];if ((GMThreadp->Flags&GMTHREAD_SUSPEND)==0){GMThreadp->SleepMillisecondDot = GetTickCount()+Milliseconds;GMThreadp->Flags = GMTHREAD_SLEEP;}//線程切換Scheduling();return ; }void ThreadPolling() {unsigned char StackPage[GMTHREADSTACKSIZE];memset(StackPage,0,GMTHREADSTACKSIZE);//模擬線程切換IdleGMThread(StackPage);return ; }//--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- 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) {for (;;){vmmprint(_SELF,__LINE__,"Thread2 \n");GMSleep(500);}return ; }void Thread3(void *lpParameter) {for (;;){vmmprint(_SELF,__LINE__,"Thread3 \n");GMSleep(800);}return ; }void Thread4(void *lpParameter) {for (;;){vmmprint(_SELF,__LINE__,"Thread4 \n");GMSleep(200);}return ; }總結(jié)
總結(jié)
以上是生活随笔為你收集整理的Windows进程与线程学习笔记(五)—— 模拟线程切换的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows进程与线程学习笔记(四)—
- 下一篇: pwn学习总结(一) —— 常用命令