Windows驱动线程创建与退出
2021-07-01
380
1
在应用层时,我们可以使用CreateThread来创建一个线程,这时如果创建成功,会退回一个线程句柄。
而当创建的这个线程退出时,这个线程变为激活态,即我们可以通过WatiForSingleObject返回WAIT_OBJECT_0.
如:
HANDLE hThread = CreateThread(...);
if(hThread != NULL)
{
DWORD dwReturn = WaitForSingleObject(hThread, INFINITE);
if(WAIT_OBJECT_0 == dwReturn)
{
//线程已经退出了
}
}
不规则的写法:
经常有人不是等待线程句柄,而是等待的是一个事件,而这个事件是线程函数退出时将这个事件激活。
当然这种写法从代码运行的角度来讲,是可用的。不过会有一个问题,就是这个线程其实没有真正的退出,将来会退出,一般认为是这个线程函数返回。其实真正的退出是不光这个函数退出,关于这个线程相关的资源也要释放掉。
这就相当于我们与了一个函数,main函数完成退出了我们就认为这个进程就结束了,其实不然。
在应用层我们是通过等待线程的句柄来实现的,那么在应用层呢。
我们先看函数
NTSTATUS
PsCreateSystemThread(
OUT PHANDLE ThreadHandle,
IN ULONG DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ProcessHandle OPTIONAL,
OUT PCLIENT_ID ClientId OPTIONAL,
IN PKSTART_ROUTINE StartRoutine,
IN PVOID StartContext
);
我们可以看到,创建线程的函数返回一个变量ThreadHandle,线程句柄,而KeWaitForSingleObject等待的是一个内核对象,所以我们应进行句柄到内核对象的转化。
NTSTATUS
KeWaitForSingleObject(
IN PVOID Object,
IN KWAIT_REASON WaitReason,
IN KPROCESSOR_MODE WaitMode,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Timeout OPTIONAL
);
句柄与内核对象的转化,windows提供了一个函数ObReferenceObjectByHandle来实现。
所以我们通过ObReferenceObjectByHandle返回其内核对象,就可以了。
HANDLE hthread = NULL;
status = PsCreateSystemThread(&hthread, THREAD_ALL_ACCESS, NULL, NULL, NULL, (PKSTART_ROUTINE)ThreadProcess, context);
if (!NT_SUCCESS(status))
{
...
}
ObReferenceObjectByHandle(hthread, THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID*)&g_thread, NULL);
ZwClose(hthread);
等待线程退出
KeWaitForSingleObject(g_thread, Executive, KernelMode, FALSE, NULL);
ObDereferenceObject(deviceExtension->thread);
题外话
其实在应用层等的是句柄,其核心其实调用的是内核的KeWaitForSingleObject来等待。