Windows线程挂起和Context
一、线程挂起(暂停)
1、SuspendThread用来暂停一个线程的执行,线程暂停时,不会被调度执行
2、ResumeThread用来恢复一个暂停线程的执行(一个暂停的线程无法调用这个方法来恢复自己,
3、因为暂停的线程不可能被执行)暂停县城总是立即被暂停,而不管被暂停的线程执行到了哪个指令
线程内核对象内部,存储了一个暂停计数的值,每调用一次,SuspendThread方法该值就加1,调用ResumeThread一次该值就减1当该值为0时,就表示该线程可以被调用执行了,但不会被立即执行,所以多次被Suspend的线程不能期望调用一次Resume方法就恢复
4、这两个方法入口参数为线程的句柄
5、线程函数内部可以通过Sleep或者SleepEx方法自行暂停一定时间后自动恢复执行,但是这个暂停时间对于系统调度程序来说只是一个参考值,调度程序不能保证精确的暂停指定的时长,通常暂停时长会长于指定的暂停时长
二、线程的暂停式创建(下面例子1)
1、在调用CreateThread创建线程时,可以明确指定以暂停方式创建线程(CREATE_SUSPENDED)
2、如果没有暂停方式执行的话,创建线程的行为将比较难以控制,有可能调度程序在CreateThread返回
前就开始执行新线程,也有可能在返回之后才去调度执行新线程,很难预期
3、所以,推荐创建线程都以暂停标志创建知道CreateThread返回,并做了一些必要的处理后,再使用
ResumeThread方法恢复新建的线程使其有机会被执行
4、这种创建线程的方式被称为暂停式创建
5、GRSLib都使用这种方式来新建线程
三、现成的CONTEXT环境(寄存器状态)
1、当新线程暂停时,可以使用GetThreadContext函数得到线程的寄存器环境,被称为线程上下文或环境块
2、该结构定义再MSDN无说明,需要在WinNT.h中查看
3、使用CONTEXT时,需要对其成员ConTextFlags,指定一系列需要得到的寄存器值的标志
4、一般给CONTEXT_ALL或者CONTEXT_FULL值即可得到主要的CPU寄存器的值,其余值再WinNT.h
中定义
5、修改CONTEXT中的对应寄存器变量的值后,可以通过调用SetThreadContext方法,将修改后的寄存器值
设置到线程中,然后再恢复线程的执行,就可以让线程使用新的寄存器的值
6、修改寄存器的方法一般用于调试或异常处理
7、不能通过这里描述的国产修改系统内核级的寄存器状态值,但可以得到他们(比如:CS,DS,SS,ES,FS,GS)
#include<windows.h>
#include<tchar.h>
#include<strsafe.h>
#define GRS_USEPRINTF() TCHAR pBuf[1024]={}
#define GRS_PRINTF(...)\
StringCchPrintf(pBuf, 1024, __VA_ARGS__); \
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), pBuf, lstrlen(pBuf), NULL, NULL);
DWORD WINAPI ThreadFunction(LPVOID lpParam)
{
//线程函数
GRS_USEPRINTF();
GRS_PRINTF(_T("Thread(0x%x) Running!\n"),GetCurrentThreadId());
return 0;
}
int _tmain()
{
GRS_USEPRINTF();
//以暂停方式创建线程
HANDLE hThread = CreateThread(NULL,0,ThreadFunction,NULL,CREATE_SUSPENDED,NULL);
ResumeThread(hThread);
GRS_PRINTF(_T("Thread Resume!\n"));
CloseHandle(hThread);
_tsystem(_T("PAUSE"));
return 0;
}
#include<windows.h>
#include<tchar.h>
#include<strsafe.h>
#define GRS_USEPRINTF() TCHAR pBuf[1024]={}
#define GRS_PRINTF(...)\
StringCchPrintf(pBuf, 1024, __VA_ARGS__); \
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), pBuf, lstrlen(pBuf), NULL, NULL);
DWORD WINAPI ThreadFunction(LPVOID lpParam)
{
//线程函数
HANDLE hEvent = (HANDLE)lpParam;
WaitForSingleObject(hEvent,INFINITE);
CloseHandle(hEvent);
return 0;
}
int _tmain()
{
HANDLE hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
HANDLE hEventDup = NULL;
DuplicateHandle(GetCurrentProcess(),hEvent,GetCurrentProcess(),&hEventDup,
DUPLICATE_SAME_ACCESS,FALSE,0);
HANDLE hThread = CreateThread(NULL, 0, ThreadFunction, hEventDup, CREATE_SUSPENDED,NULL);
ResumeThread(hThread);
SuspendThread(hThread);
CONTEXT ct = {};
ct.ContextFlags = CONTEXT_ALL;
GetThreadContext(hThread,&ct);
ResumeThread(hThread);
SetEvent(hEvent);
CloseHandle(hEvent);
_tsystem(_T("PAUSE"));
return 0;
}
该文章会更新,欢迎大家批评指正。文章来源:https://www.toymoban.com/news/detail-542005.html
推荐一个零声学院免费公开课程,个人觉得老师讲得不错,
分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:
服务器课程:C++服务器文章来源地址https://www.toymoban.com/news/detail-542005.html
到了这里,关于Windows线程挂起和Context的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!