日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

Windows进程与线程学习笔记(五)—— 模拟线程切换

發布時間:2025/3/21 windows 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Windows进程与线程学习笔记(五)—— 模拟线程切换 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Windows進程與線程學習筆記(五)—— 模擬線程切換

    • ThreadSwitch代碼分析
      • ThreadSwitch.cpp
      • ThreadCore.h
      • ThreadCore.cpp
    • 總結

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[]) {//初始化線程環境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; // 線程名 相當于線程TIDint Flags; // 線程狀態int SleepMillisecondDot; // 休眠時間void *InitialStack; // 線程堆棧起始位置,也就是EBPvoid *StackLimit; // 線程堆棧界限void *KernelStack; // 線程堆棧當前位置,也就是ESPvoid *lpParameter; // 線程函數的參數void (*func)(void *lpParameter); // 線程函數} GMThread_t; //--------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------/* 線程結構體數組* 線程在不同狀態的存儲位置不同* 正在運行的線程位于KPCR* 等待中的線程位于等待鏈表* 就緒的線程位于調度鏈表中* 這里對于以上三種情況使用一個數組進行包含* main函數也是一個線程,信息存在第一個數組成員里,也就是下標為0的位置* 創建線程時,是從下標為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{//保存現場push ebpmov ebp,esp//sub esp,__LOCAL_SIZEpush edipush esipush ebxpush ecxpush edxpush eaxmov esi,SrcGMThreadp //當前線程結構體指針mov edi,DstGMThreadp //目標線程結構體指針// esi + GMThread_t.KernelStack == SrcGMThreadp.KernelStackmov [esi+GMThread_t.KernelStack], esp//---------------經典堆棧切換 另一個線程復活----------------------------------// edi + GMThread_t.KernelStack == DstGMThreadp.KernelStackmov esp, [edi+GMThread_t.KernelStack]//此時,ESP為目標線程堆棧棧頂pop eaxpop edxpop ecxpop ebxpop esipop edi//add esp,__LOCAL_SIZEpop ebpret //ebp之后是GMThreadStartup函數地址} }//用來執行線程函數 void GMThreadStartup(GMThread_t *GMThreadp) {//執行線程函數GMThreadp->func(GMThreadp->lpParameter);//線程函數執行結束,設置線程狀態為EXITGMThreadp->Flags = GMTHREAD_EXIT;//線程切換Scheduling();return ; }void IdleGMThread(void *lpParameter) {Scheduling();return ; }void PushStack(unsigned int **Stackpp,unsigned int v) {// ESP 減去一個單位(4個字節)*Stackpp -= 1;//[ESP] = 參數v**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);//堆棧棧底(EBP)GMThreadp->InitialStack = (StackPages+GMTHREADSTACKSIZE-0x10);//堆棧邊界地址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 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//執行后,堆棧變化如下

GMThreadp->KernelStack = StackDWORDParam; //指向當前線程的棧頂(ESP)GMThreadp->Flags = GMTHREAD_READAY; //線程狀態設置為就緒return ; }int RegisterGMThread(char *name,void (*func)(void *lpParameter),void *lpParameter) {int i;//為數組下標為0的成員賦值,GM Thread,相當于main函數線程if (GMThreadList[0].name==NULL){//申請堆棧初始化操作 線程數組 ,線程名字 ,函數地址 ,參數initGMThread(&GMThreadList[0], "IDLE GM Thread", IdleGMThread, NULL);}//新增的線程從下標為1開始寫入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(void) {int i;int TickCount;GMThread_t *SrcGMThreadp;GMThread_t *DstGMThreadp;TickCount = GetTickCount();SrcGMThreadp = &GMThreadList[CurrentThreadindex]; //當前線程結構體指針DstGMThreadp = &GMThreadList[0]; //目標線程結構體指針//遍歷線程數組,找到狀態為就緒的線程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)){//檢測到有線程的狀態為就緒,將其作為目標線程DstGMThreadp = &GMThreadList[i];break;}}CurrentThreadindex = DstGMThreadp-GMThreadList; //得到即將執行的線程下標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 ; }

總結

  • 線程不是被動切換的,而是主動讓出CPU
  • 線程切換并沒有使用TSS來保存寄存器,而是使用堆棧
  • 線程切換的過程就是堆棧切換的過程
  • 總結

    以上是生活随笔為你收集整理的Windows进程与线程学习笔记(五)—— 模拟线程切换的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。