线程操做函数

线程的挂起和恢复

DWORD SuspendThread ( HANDLE hThread );   //挂起线程函数

DWORD ResumeThread ( HANDLE hThread );   //恢复线程spa

SuspendThread  ResumeThread 都返回以前的挂起计数。操作系统

一个线程最多能够挂起MAXIMUM_SUSPEND_COUNT (WinNT.h中定义为127次)。线程

 

进程的挂起和恢复

对于Windows来讲,不存在暂停或恢复进程的概念,由于进程历来不会被安排得到cpu时间。指针

可是咱们能够建立一个函数,用来挂起或者恢复进程中的所有线程,这样就能挂起或者恢复一个进程了。调试

参考代码以下:对象

#include <Windows.h>进程

#include <stdio.h>ip

#include <Tlhelp32.h>内存

//dwProcessID参数为须要挂起或者恢复的进程ID

// bSuspend参数若是为TRUE就挂起进程,不然恢复进程

void SuspendProcess(DWORD dwProcessID, BOOL bSuspend)

{

         HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwProcessID);                    //得到系统内因此线程

         if (hSnapshot != INVALID_HANDLE_VALUE)

         {

                   THREADENTRY32 te;

                   ZeroMemory(&te, sizeof(te));

                   te.dwSize = sizeof(te);

 

                   BOOL bOK = Thread32First(hSnapshot, &te);  

                   for (; bOK; bOK = Thread32Next(hSnapshot, &te))

                   {

                            if (te.th32OwnerProcessID == dwProcessID)          //必须制定,不然程序会尝试挂起系统内全部的线程,就会致使死机

                            {

                                     HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID);

                                     if (hThread != NULL)

                                     {

                                               if (bSuspend)

                                               {

                                                        SuspendThread(hThread);

                                               }

                                               else

                                                        ResumeThread(hThread);

                                     }

                                     CloseHandle(hThread);

                            }

                   }

         }

         CloseHandle(hSnapshot);

}

int main(void)

{

         SuspendProcess(9636, FALSE);

         return 0;

}

 

睡眠

VOID Sleep (DWORD dwMilliseconds);

这个函数将使线程本身挂起 dwMilliseconds 长的时间。

1.       调用Sleep,可以使线程自愿放弃它剩余的时间片。

2. 系统将在大约的指定毫秒数内使线程不可调度。不错,若是告诉系统,想睡眠 100ms,那么能够睡眠大约这么长时间,可是也可能睡眠数秒钟或者数分钟。记住,Windows不是个实时操做系统。虽然线程可能在规定的时间被唤醒,可是它可否作到,取决于系统中还有什么操做正在进行。

3.能够调用Sleep,而且为dwMilliseconds参数传递INFINITE。这将告诉系统永远不要调度该线程。这不是一件值得去作的事情。最好是让线程退出,并还原它的堆栈和内核对象。

4. 能够将0传递给Sleep。这将告诉系统,调用线程将释放剩余的时间片,并迫使系统调度另外一个线程。可是,系统能够对刚刚调用 Sleep的线程从新调度。Sleep(0)是指CPU交出当前线程的执行权,让CPU去执行其余线程。也就是放弃当前线程的时间片,转而执行其余线程

 

切换到另外一个线程

BOOL SwitchToThread (void);

当调用这个函数的时候,系统要查看是否存在一个迫切须要CPU时间的线程。若是没有线程迫切须要CPU时间,SwitchToThread就会当即返回。若是存在一个迫切须要 CPU时间的线程,SwitchToThread就对该线程进行调度(该线程的优先级可能低于调用 SwitchToThread的线程)。

这个迫切须要CPU时间的线程能够运行一个时间段,而后系统调度程序照常运行。该函数容许一个须要资源的线程强制另外一个优先级较低、而目前却拥有该资源的线程放弃该资源。若是调用 SwitchToThread函数时没有其余线程可以运行,那么该函数返回 FALSE,不然返回一个非0值。

Sleep():时间片只能让给优先级相同或更高的线程;

SwitchToThread():只要有可调度线程,即使优先级较低,也会让其调度。

 

在实际上下文中谈CONTEXT结构

CONTEXT结构包括如下部分:

   CONTEXT_CONTROL:包含CPU的控制寄存器,好比指今指针,堆栈指针,标志和函数返回地址..AX, BX, CX, DX, SI, D
     CONTEXT_INTEGER:用于标识CPU的整数寄存器.DS, ES, FS, GS
   CONTEXT_FLOATING_POINT:用于标识CPU的浮点寄存器.
     CONTEXT_SEGMENTS:用于标识CPU的段寄存器.SS:SP, CS:IP, FLAGS, BP
   CONTEXT_DEBUG_REGISTER:用于标识CPU的调试寄存器.  
   CONTEXT_EXTENDED_REGISTERS:用于标识CPU的扩展寄存器I
   CONTEXT_FULL:至关于CONTEXT_CONTROL or CONTEXT_INTEGER or   CONTEXT_SEGMENTS,即这三个标志的组合

 

 

咱们可使用GetThreadContext函数来查看线程内核对象的内部,并获取当前CPU寄存器状态的集合。

BOOL GetThreadContext (

HANDLE  hThread,

PCONTEXT  pContext)

若要调用该函数,只需指定一个CONTEXT结构,对某些标志(该结构的ContextFlags成员)进行初始化,指明想要收回哪些寄存器,并将该结构的地址传递给GetThreadContext 。而后该函数将数据填入你要求的成员。

在调用GetThreadContext函数以前,应该调用SuspendThread,不然,线程可能恰好被调度,这样一来,线程的上下文就和所获取的信息不一致了。

示例代码以下: 

         CONTEXT Context;                  //定义一个CONTEXT结构

 

         Context.ContextFlags = CONTEXT_CONTROL;    //告诉系统咱们想获取线程控制寄存器的内容   

         GetThreadContext(hThread, &Context);      //调用GetThreadContext获取相关信息

Ps:在调用GetThreadContext函数以前,必须首先初始化CONTEXT结构的ContextFlags成员。

要得到线程的全部重要的寄存器(也就是微软认为最经常使用的寄存器),应该像下面同样初始化ContextFlags:

Context.ContextFlags = CONTEXT_FULL;

WinNT. h头文件中,定义了CONTEXT_FULLCONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS

 

固然,咱们还能够经过调用SetThreadContext函数来改变结构中的成员,并把新的寄存器值放回线程的内核对象中

BOOL SetThreadContext (

HANDLE  hThread,

CONST CONTEXT  *pContext)

一样,若是要改变哪一个线程的上下文,应该先暂停该线程。       

         CONTEXT Context;      //定义一个CONTEXT结构      

         SuspendThread(hThread);  //挂起线程  

         Context.ContextFlags = CONTEXT_CONTROL;   //获取当前上下文的值

         GetThreadContext(hThread, &Context);

 

         Context.Eip = 0x00010000;      //Eip字段存储的是指令指针,如今让指令指针指向地址 0x00010000;

         Context.ContextFlags = CONTEXT_CONTROL;

 

         SetThreadContext(hThread, &Context);   //从新设置线程上下文

 

         ResumeThread(hThread);         //恢复线程,如今线程开始从0x00010000这个地方开始执行指令

 

线程的优先级

优先级为0的线程:系统启动时,会建立一个优先级为0的“页面清零线程”,它只有在系统中没有其余可调度线程时,才能调度,用来清除内存中的闲置页面。

优先级在1 ~ 15之间的线程:通常用户模式下,线程的优先级都在该范围。

优先级在16 ~ 30之间的线程:通常是内核线程。

 

一旦进程运行,即可以经过调用SetPriorityClass来改变本身的优先级

BOOL SetPriorityClass(

         HANDLE  hProcess

         DWORD  fdwPriority);

用来获取进程优先级:

DWORD GetPriorityClass( HANDLE  hProcess );

 

设置和获取线程的相对优先级:

BOOL SetThreadPriority (

         HANDLE  hThread,

         Int  nPriority);

Int GetThreadPriority(HANDLE  hThread);

 

容许或者禁止进程或者线程动态提高本身的优先级:

BOOL SetProcessPriorityBoost(

         HANDLE  hProcess,

         BOOL  bDisablePriorityBoost);

 BOOL SetThreadPriorityBoost(

         HANDLE  hThread,

         BOOL  bDisablePriorityBoost);

 

判断当前是否是启用优先级提高:

BOOL GetProcessPriorityBoost(

         HANDLE  hProcess,

         PBOOL  pbDisablePriorityBoost);

 BOOL GetThreadPriorityBoost(

         HANDLE  hThread,

         PBOOL  pbDisablePriorityBoost);

 

在多CPU的状况下,咱们能够限制某些线程只在可用的cpu的一个子集上运行:

BOOL SetProcessAffinityMask(

         HANDLE  hProcess

         DWORD_PTR  dwProcessAffinityMask);

第一个参数hProcess表明要设置的进程。第二个参数dwProcessAffinityMask是一个位掩码,表明线程能够在哪些CPU上运行。例如,传入0x00000005意味着这个进程中的线程能够在CPU 0 和 CPU 2上运行,可是不能在CPU 1 和 CPU 3~31上运行。

 

获取进程的关联性掩码:

BOOL GetProcessAffinityMask(

         HANDLE  hProcess

         PDWORD_PTR  pdwProcessAffinityMask,

PDWORD_PTR  pdwSystemAffinityMask);

设置线程的关联性掩码:

BOOL SetThreadAffinityMask(

         HANDLE  hThread

         DWORD_PTR  dwThreadAffinityMask);

 

有时候强制一个线程只是用特定的某个CPU并非什么好主意。例如,若是有三个线程都只能使用CPU0,而CPU1,CPU2和CPU3却无所事事。咱们想让一个线程运行在一个CPU上,可是同时系统也容许他移到另外一个空闲的CPU,那就更好了。要给线程设置一个理想的CPU,能够调用以下:

DWORD SetThreadIdealProcessor(

         HANDLE  hThread,

         DWORD  dwIdealProcessor);

hThread用于指明要为哪一个线程设置首选CPU。

dwIdealProcessor函数不是个位掩码,它是个从0到31/63,用于指明供线程但愿使用的首选CPU 。能够传递一个MAXIMUM_PROCESSORS的值(在WinNT.h中定义,在32位操做系统中定义为32,64位操做系统中定义为64),代表线程没有理想的CPU。若是没有为该线程设置理想的CPU,那么该函数返回前一个理想的CPU或MAXIMUM_PROCESSORS。

相关文章
相关标签/搜索