內核函數PsCreateSystemThread負責建立新線程。該函數能夠建立兩種線程,一種是用戶線程,它屬於當前進程中的線程。另外一種是系統線程,系統線程不屬於當前用戶進程,而是屬於系統進程,通常PID爲4,名字爲「System」的進程。html
NTSTATUS PsCreateSystemThread( OUT PHANDLE ThreadHandle, //新建立的線程句柄 IN ULONG DesiredAccess, //建立的權限 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,//線程的屬性,通常設爲NULL IN HANDLE ProcessHandle OPTIONAL,//指定建立用戶線程仍是系統線程。若是爲NULL,則爲系統進程,若是該值是一個進程句柄,則新建立的線程屬於這個指定的進程。DDK提供的NTCurrentProcess能夠獲得當前進程的句柄。 OUT PCLIENT_ID ClientId OPTIONAL, IN PKSTART_ROUTINE StartRoutine,//新線程的運行地址 IN PVOID StartContext //新線程接收的參數 );
在內核模式下建立的線程是沒法自動退出的,必須使用PsTerminateSystemThread強制結束線程。函數
經過內核事件KEVENT和內核等待KeWaitForSingleObject來演示事件的建立過程。spa
KEVENT Event; //建立一個同步事件 KeInitializeEvent( &Event, //要初始化的KEVENT結構對象 SynchronizationEvent, //事件類型 FALSE);
KeSetEvent(
&Event, //被激活的事件
IO_NO_INCREMENT, //被喚醒線程臨時提高線程優先級的增量,傳0
FALSE); //If TRUE, the KeSetEvent call must be followed by a call to KeWaitForMultipleObjects, KeWaitForMutexObject, or KeWaitForSingleObject.線程
KeWaitForSingleObject( &Event, //同步對象的指針, Executive, //等待的緣由,通常爲Executive KernelMode, //等待模式,通常爲KernelMode FALSE, //指明等待是否爲「警戒」的,通常爲FALSE NULL); //等待時間,若是爲NULL,就表示無限期等待,直到同步對象變爲激發態 DbgPrint("ThreadProcedure() Exit\r\n"); PsTerminateSystemThread(STATUS_SUCCESS);
總結一下代碼流程:指針
1.驅動程序KeInitializeEvent建立了一個內核事件
htm
2.PsCreateSystemThread建立新的系統線程,將建立好的KEVENT結構傳參給新建立的線程。 再調用KeSetEvent將事件激活對象
3.線程中調用KeWaitForSingleObject等待事件激活狀態(受信),執行後續代碼,最後PsTerminateSystemThread結束線程。blog
源代碼:進程
KEvent.h事件
#pragma once #include <ntifs.h> #define DELAY_ONE_MICROSECOND (-10) #define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000) VOID DriverUnload(PDRIVER_OBJECT DriverObject); VOID KSleep(LONG MilliSecond); void ThreadProcedure(PVOID ParameterData);
KEvent.c
#include "KEvent.h" //http://www.cnblogs.com/dacainiao/p/5923147.html //同步事件(SynchronizationEvent) //當事件對象爲激發時,如遇到KeWaitForXX等內核函數,事件對象則自動變回未激發態 //通知事件(NotificationEvent) //當事件對象爲激發時,如遇到KeWaitForXX等內核函數,事件對象則不會變回未激發態 NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath) { int i = 0; NTSTATUS Status = STATUS_SUCCESS; HANDLE ThreadHandle = NULL; PDEVICE_OBJECT DeviceObject = NULL; KEVENT Event; CLIENT_ID ClientID = {0}; DriverObject->DriverUnload = DriverUnload; //建立一個同步事件 KeInitializeEvent( &Event, //要初始化的KEVENT結構對象 SynchronizationEvent, //事件類型 FALSE); //若是爲真,初始爲激發態 //建立一個通知事件 //KeInitializeEvent(&Event, NotificationEvent, // FALSE); //建立一個System進程下運行的線程 for (i=0;i<2;i++) { Status = PsCreateSystemThread( &ThreadHandle, //新建立的線程句柄 0, //建立的權限 NULL, //線程的屬性,通常設爲NULL NtCurrentProcess(), //指定建立用戶線程仍是系統線程。若是爲NULL,則爲系統進程,若是該值是一個進程句柄,則新建立的線程屬於這個指定的進程。DDK的NTCurrentProcess能夠獲得當前進程的句柄。 &ClientID, (PKSTART_ROUTINE)ThreadProcedure, //新線程的運行地址 (PVOID)&Event); //新線程接收的參數 } KSleep(3000); KeSetEvent( &Event, //被激活的事件 IO_NO_INCREMENT, //被喚醒線程臨時提高線程優先級的增量,傳0 FALSE); //If TRUE, the KeSetEvent call must be followed by a call to KeWaitForMultipleObjects, KeWaitForMutexObject, or KeWaitForSingleObject. return Status; } void ThreadProcedure(PVOID ParameterData) { KEVENT Event = *((PKEVENT)ParameterData); NTSTATUS Status; KeWaitForSingleObject( &Event, //同步對象的指針, Executive, //等待的緣由,通常爲Executive KernelMode, //等待模式,通常爲KernelMode FALSE, //指明等待是否爲「警戒」的,通常爲FALSE NULL); //等待時間,若是爲NULL,就表示無限期等待,直到同步對象變爲激發態 DbgPrint("ThreadProcedure() Exit\r\n"); PsTerminateSystemThread(STATUS_SUCCESS); } VOID DriverUnload(PDRIVER_OBJECT DriverObject) { DbgPrint("DriverUnload()\r\n"); } VOID KSleep(LONG MilliSecond) { LARGE_INTEGER Interval = {0}; Interval.QuadPart = DELAY_ONE_MILLISECOND; Interval.QuadPart *= MilliSecond; KeDelayExecutionThread(KernelMode, 0, &Interval); }