读书笔记:Windows核心编程第七章---线程的调度、优先级和亲缘性
抢占式操作系统必须通过某种算法来确定那些线程应该何时调度和运行时间的长短。。。每个线程拥有一个上下文结构,这个结构维护在线程的内核对象中,他反映了线程上次运行时候该线程的CPU寄存器状态。。。当他可调度时候,系统将他的上下文加载到CPU的寄存器中。。。
CreateProcess和CreateThread时候看是否传递了CREATE_SUSPENDED标志。线程或着进程创建时候的暂停计数是1,之后初始化完毕以后如果没有传送该标志那么计数器减一。。。
DWORDResumeThread(HANDLEhThread)暂停计数减一
DWORDSuspendThread(HANDLEhThread)暂停计数加一
线程能够自行暂停,但是不能自行恢复,暂停多少次就要恢复多少次。。。最大次数127次。。。
我们能够自己写一个函数暂停进程的所有线程的运行,但是这个基于你对自己的进程有足够的了解的情况下。
{
HANDLE nSapshot =CreateToolHelp32Snapshot(TH32CS_SNAPTHREAD,dwProcessID);
If (nSapshot ! =INCALID_HANDLE_VALUE){
ThreEADENTRY32 te = { sizeof(te) };
BOOLfOk = Thread32First(nSapshot,&te);
For(;fOk;fOk= Thread32Next(nSapshot,&te)){
If(te.th320wnerProcessID == dwProcessID){
HANDLE hThread =OpenThread(THREAD_SUSPEND_RESUME,FALSE,te.the32tThreadID));
If(hThread!= NULL){
If(fSuspend)
SuspendThread(hThread);
Else
ResumeThread(hThread);
}
CloseHandle(hThread);
}
}
CloseHandle(nSapshot);
}
VOID Sleep(DWORD dweMilliseconds);
CPU自愿放弃他剩余时间片,并在指定的时间内不可调度。。。
BOOL SwitchToThread();
当调用这个函数的时候,系统要查看是否存在一个迫切需要C P U时间的线程。如果没有线程迫切需要C P U时间,S w i t c h To T h r e ad就会立即返回。调用S w it c h To T h r e a d函数与调用S l ee p是相似的,并且传递给它一个0 m s的超时。差别是S w i t c h To T h r e ad允许优先级较低的线程运行。即使低优先级线程迫切需要C P U时间,S l e e p也能够立即对调用线程重新进行调度。
我们可以使用GetTickCount();这个是在程序没有被中断的情况下,在抢占式系统中他是不准确的。。。
BOOL GetThreadTimes(
HANDLE nThread;
PFILETIME pftExitTime;
PFILETIMEpftKernelTime;
PFILETIMEpftUserTime;
);
BOOL GetProcessTimes(
HANDLE nProcess;
PFILETIME pftCreationTime;
PFILETIME pftExitTime;
PFILETIMEpftKernelTime;
PFILETIMEpftUserTime;
);
G e t P r o c e s s Ti me s是个类似G e tT h r e a d Ti m e s的函数,适用于进程中的所有线程(甚至是已经终止运行的线程)。返回的时间是所有进程的线程在代码中经过的全部时间的总和。
环境结构在线程调度中所起的重要作用了。环境结构使得系统能够记住线程
的状态,这样,当下次线程拥有可以运行的C P U时,它就能够找到它上次中断运行的地方。
C O N T E X T结构包含了特定处理器的寄存器数据。系统使用C O NT E X T结构执行各种内部操作。目前,已经存在为I n te l、M I PS、A l ph a和P o we r P C处理器定义的C O NT E X T结构。若要了解这些结构的定义,参见头文件Wi nN T. h
Wi n d o w s实际上允许查看线程内核对象的内部情况,以便抓取它当前的一组C P U寄存器。
HANDLEhThread,
PCONTEXTpContext);
在调用G e tT h r e a d C o n t e x t函数之前,应该调用S u sp e n d T h r e a d,否则,线程可能被调度,而且线程的环境可能与你收回的不同。一个线程实际上有两个环境。一个是用户方式,一个是内核方式。G e tT h r e a d C o n t e x t只能返回线程的用户方式环境。如果调用S u sp e n d T h r e a d来停止线程的运行,但是该线程目前正在用内核方式运行,那么,即使S u sp e n d T h r e a d实际上尚未暂停该150计计第二部分编程的具体方法下载线程的运行,它的用户方式仍然处于稳定状态。线程在恢复用户方式之前,它无法执行更多的用户方式代码,因此可以放心地将线程视为处于暂停状态,G e tT h r e a d C o n t e x t函数将能正常运行。
然后通过调用S e tT h r e a d C o n t e x t将新寄存器值放回线程的内核对象中:
BOOL SetThreadContext(
HANDLEhThread,
CONSTPCONTEXT *pContext);
进程优先级调整:
BOOLSetPriorityClass(
HANDLE hProcess;
DWORD fdwPriority;);
BOOLGetPriorityClass(
HANDLE hProcess;);
线程优先级调整:
BOOL GetThreadPriority(
HANDLE hThread;
DWORD fdwPriority;);
BOOL SetThreadPriority(
HANDLE hThread;);
操作系统能够为前台程序动态提高优先级,对渴求线程动态提高优先级;
上次运行的那个处理器上运行线程。让线程留在单个处理器上,有助于重复使用仍然在处理器的内存高速缓存中的数据。
BOOL SetProcessAffinityMask(
HANDLE hProcess,
DWORD_PTR dwProcessAffinityMask);
BOOL SetProcessAffinityMask(
HANDLE hProcess,
DWORD_PTR dwProcessAffinityMask,
DWORD_PTR dwSystemAffinityMask);
通过调用S e tT h r e a d A ff i n i t y M a s k,就能为各个线程设置亲缘性屏蔽:
BOOL SetThreadAffinityMask(
HANDLE hThread,
DWORD_PTR dwProcessAffinityMask);
BOOL SetThreadIdeaProcessor(
HANDLE hThread,
DWORD DwiIdeaProcessor);
第一个参数h P ro c e s s用于指明要影响的是哪个进程。第二个参数d w Pr o c e s s A ff i n i t y M a s k是个位屏蔽,用于指明线程可以在哪些C P U上运行。
在同一个CPU的同一个缓存中执行的程序执行速度大大加快…