自旋锁
#include <ntddk.h>
#include <windef.h>
VOID Unload(IN PDRIVER_OBJECT pDriverObject)
{
KdPrint(("Goodbye driver\n"));
}
VOID SpinLockTest()
{
KSPIN_LOCK SpinLock;
KIRQL irql;
KeInitializeSpinLock(&SpinLock);
switch (KeGetCurrentIrql())
{
case DISPATCH_LEVEL:
KdPrint(("DISPATCH_LEVEL\n"));
break;
case APC_LEVEL:
KdPrint(("APC_LEVEL\n"));
break;
case PASSIVE_LEVEL:
KdPrint(("PASSIVE_LEVEL\n"));
break;
default:
break;
}
KeAcquireSpinLock(&SpinLock, &irql);
switch (KeGetCurrentIrql())
{
case DISPATCH_LEVEL:
KdPrint(("DISPATCH_LEVEL\n"));
break;
case APC_LEVEL:
KdPrint(("APC_LEVEL\n"));
break;
case PASSIVE_LEVEL:
KdPrint(("PASSIVE_LEVEL\n"));
break;
default:
break;
}
KeReleaseSpinLock(&SpinLock, irql);
switch (KeGetCurrentIrql())
{
case DISPATCH_LEVEL:
KdPrint(("DISPATCH_LEVEL\n"));
break;
case APC_LEVEL:
KdPrint(("APC_LEVEL\n"));
break;
case PASSIVE_LEVEL:
KdPrint(("PASSIVE_LEVEL\n"));
break;
default:
break;
}
}
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
KdPrint(("Hello driver\n"));
DriverObject->DriverUnload = Unload;
SpinLockTest();
return STATUS_SUCCESS;
}
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/28b8b88082fb08d998f8b05ffaa0120e.png)
用户模式下的同步对象
用户模式下的事件
对象 | 描述 |
---|
Event(事件) | 阻塞一个线程直到其他线程检测到某事件发生 |
Semaphore(信号灯) | 与事件对象相似,但可以满足任意数量的等待 |
Mutex(互斥) | 执行到关键代码段时,禁止其他线程执行该代码段 |
Thread(线程) | 阻塞一个线程直到另一个线程结束 |
#include <windows.h>
#include <stdio.h>
DWORD WINAPI Threadproc(PVOID Context)
{
PHANDLE phEvent = (PHANDLE)Context;
printf("进入到线程函数里\n");
SetEvent(*phEvent);
printf("线程函数结束\n");
return 0;
}
int main()
{
HANDLE hEvent= CreateEvent(NULL, FALSE, FALSE, NULL);
if (NULL==hEvent)
{
printf("创建事件失败%d\n", GetLastError());
return -1;
}
CreateThread(NULL, 0, Threadproc, &hEvent, 0, NULL);
WaitForSingleObject(hEvent, INFINITE);
printf("进程结束");
return 0;
}
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/0ae627011ec7fd3588558387759d1a1b.png)
用户模式下的信号灯
DWORD WINAPI Threadproc(PVOID Context)
{
//首先创建一个事件,得到事件句柄
PHANDLE phSemaphore = (PHANDLE)Context;
printf("进入到线程函数\n");
Sleep(5000);
ReleaseSemaphore(*phSemaphore, 1, NULL);
printf("线程函数结束\n");
return 0;
}
int main()
{
//设置两个信号
HANDLE hSemaphore = CreateSemaphore(NULL, 2, 2, NULL);
if (NULL == hSemaphore)
{
printf("信号量创建失败%d\n", GetLastError());
return -1;
}
//设置有信号状态,此时这个等待就会结束
WaitForSingleObject(hSemaphore, INFINITE);
WaitForSingleObject(hSemaphore, INFINITE);
//设置两个信号,当出现第三个信号,如果前面没有释放将会卡住,把下面一行注释掉将会卡住
//Threadproc里面5秒后释放了一个信号所以5秒后可以输出主线程
CreateThread(NULL, 0, Threadproc,&hSemaphore,0,NULL);
WaitForSingleObject(hSemaphore, INFINITE);
printf("主线程结束");
return 0;
}
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/6a785e90895c4faec2bb0c9636d02cd3.png)
用户模式下的互斥器
#include <windows.h>
#include <stdio.h>
DWORD WINAPI Threadproc1(PVOID Context)
{
PHANDLE phMutex = (PHANDLE)Context;
WaitForSingleObject(*phMutex, INFINITE);
printf("进入到线程1\n");
Sleep(2000);
printf("线程函数结束1\n");
ReleaseMutex(*phMutex);
return 0;
}
DWORD WINAPI Threadproc2(PVOID Context)
{
PHANDLE phMutex = (PHANDLE)Context;
WaitForSingleObject(*phMutex, INFINITE);
printf("进入到线程2\n");
Sleep(2000);
printf("线程函数结束2\n");
ReleaseMutex(*phMutex);
return 0;
}
int main()
{
HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);
if (NULL == hMutex)
{
printf("创建互斥事件失败%d\n", GetLastError());
return -1;
}
HANDLE hThread[2] = { NULL };
hThread[0] =CreateThread(NULL, 0, Threadproc1, &hMutex, 0, NULL);
hThread[1] =CreateThread(NULL, 0, Threadproc2, &hMutex, 0, NULL);
WaitForMultipleObjects(2, hThread, TRUE,INFINITE);
printf("主线程结束");
return 0;
}
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/878360fce85d21db3dfb8a7e5d527044.png)
内核模式下的同步对象
内核模式下创建线程
#include <ntddk.h>
PCHAR PsGetProcessImageFileName(IN PEPROCESS Process);
VOID Unload(IN PDRIVER_OBJECT pDriverObject)
{
KdPrint(("Goodbye driver\n"));
}
VOID ThreadProc(PVOID Context)
{
PHANDLE phEvent = (PHANDLE)Context;
KdPrint(("%s\n", PsGetProcessImageFileName(PsGetCurrentProcess())));
PsTerminateSystemThread(0);
}
VOID CreateThreadTest()
{
HANDLE hThread;
HANDLE hProcess;
NTSTATUS status;
CLIENT_ID ClientId = { NULL };
OBJECT_ATTRIBUTES oa;
PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, NULL, NULL, NULL, ThreadProc, NULL);
ClientId.UniqueProcess = (HANDLE)5132;
InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
status = ZwOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &oa, &ClientId);
if (NT_SUCCESS(status))
{
KdPrint(("打开进程成功\n"));
PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, NULL, hProcess, NULL, ThreadProc, NULL);
}
else
{
KdPrint(("打开进程失败\n"));
}
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath
)
{
KdPrint(("hello driver\n"));
DriverObject->DriverUnload = Unload;
CreateThreadTest();
return STATUS_SUCCESS;
}
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/08637649991f52493ba36d0162b3f3c3.png)
内核模式下的事件
对象 | 数据类型 | 描述 |
---|
Event(事件) | KEVENT | 阻塞一个线程直到其他线程检测到某事件发生 |
Semaphore(信号灯) | KSEMAPHORE | 与事件对象相似,但可以满足任意数量的等待 |
Mutex(互斥) | KMUTEX | 执行到关键代码段时,禁止其他线程执行该代码段 |
Timer( 定时器) | KTIMER | 推迟线程执行一段时期 |
Thread(线程) | KTIMER | 阻塞一个线程直到另一个线程结束 |
#include <ntddk.h>
VOID Unload(IN PDRIVER_OBJECT pDriverObject)
{
KdPrint(("Goodbye driver\n"));
}
VOID ThreadProc1(PVOID Context)
{
PKEVENT pEvent = (PKEVENT)Context;
KdPrint(("进入线程1\n"));
KeSetEvent(pEvent, IO_NO_INCREMENT, FALSE);
PsTerminateSystemThread(0);
KdPrint(("离开线程1\n"));
}
VOID EventTest()
{
KEVENT Event;
HANDLE hThread;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
PsCreateSystemThread(&hThread,THREAD_ALL_ACCESS,NULL,NULL,NULL,ThreadProc1,&Event);
KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
KdPrint(("主线程结束\n"));
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath
)
{
KdPrint(("hello driver\n"));
DriverObject->DriverUnload = Unload;
EventTest();
return STATUS_SUCCESS;
}
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/f4097b835c18ab9aa961528fb742c88f.png)
内核模式下的信号灯
#include <ntddk.h>
VOID Unload(IN PDRIVER_OBJECT pDriverObject)
{
KdPrint(("Goodbye driver\n"));
}
VOID ThreadProc(PVOID Context)
{
LARGE_INTEGER timeout;
timeout.QuadPart = -10 * 2000 * 1000;
PKSEMAPHORE pSemaphore = (PKSEMAPHORE)Context;
KdPrint(("进入系统线程函数\n"));
KeDelayExecutionThread(KernelMode, FALSE, &timeout);
KeReleaseSemaphore(pSemaphore, IO_NO_INCREMENT, 1, FALSE);
KdPrint(("离开系统线程函数\n"));
PsTerminateSystemThread(0);
}
VOID SemaphoreTest()
{
KSEMAPHORE Semaphore;
LONG Count;
HANDLE hThread;
KeInitializeSemaphore(&Semaphore, 2, 2);
Count = KeReadStateSemaphore(&Semaphore);
KdPrint(("%d\n", Count));
KeWaitForSingleObject(&Semaphore, Executive, KernelMode, FALSE, NULL);
Count = KeReadStateSemaphore(&Semaphore);
KdPrint(("%d\n", Count));
KeWaitForSingleObject(&Semaphore, Executive, KernelMode, FALSE, NULL);
Count = KeReadStateSemaphore(&Semaphore);
KdPrint(("%d\n", Count));
PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, NULL, NULL, NULL, ThreadProc, &Semaphore);
KeWaitForSingleObject(&Semaphore, Executive, KernelMode, FALSE, NULL);
KdPrint(("结束"));
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath
)
{
KdPrint(("hello driver\n"));
DriverObject->DriverUnload = Unload;
SemaphoreTest();
return STATUS_SUCCESS;
}
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/449d25fc5100c72f426d6c3a2b1b75bc.png)
内核模式下的互斥器
#include <ntddk.h>
VOID Unload(IN PDRIVER_OBJECT pDriverObject)
{
KdPrint(("Goodbye driver\n"));
}
VOID ThreadProc1(PVOID Context)
{
LARGE_INTEGER timeout;
timeout.QuadPart = -10 * 2000 * 1000;
PKMUTEX pMutex = (PKMUTEX)Context;
KeWaitForMutexObject(pMutex, Executive, KernelMode, FALSE, NULL);
KdPrint(("进入线程1\n"));
KeDelayExecutionThread(KernelMode, FALSE, &timeout);
KdPrint(("离开线程1\n"));
KeReleaseMutex(pMutex, FALSE);
PsTerminateSystemThread(0);
}
VOID ThreadProc2(PVOID Context)
{
LARGE_INTEGER timeout;
timeout.QuadPart = -10 * 2000 * 1000;
PKMUTEX pMutex = (PKMUTEX)Context;
KeWaitForMutexObject(pMutex, Executive, KernelMode, FALSE, NULL);
KdPrint(("进入线程2\n"));
KeDelayExecutionThread(KernelMode, FALSE, &timeout);
KdPrint(("离开线程2\n"));
KeReleaseMutex(pMutex, FALSE);
PsTerminateSystemThread(0);
}
VOID MutexTest()
{
KMUTEX Mutex;
HANDLE hThread[2] = { NULL };
PETHREAD Thread[2] = { NULL };
KeInitializeMutex(&Mutex, 0);
PsCreateSystemThread(&hThread[0], THREAD_ALL_ACCESS, NULL, NULL, NULL, ThreadProc1, &Mutex);
PsCreateSystemThread(&hThread[1], THREAD_ALL_ACCESS, NULL, NULL, NULL, ThreadProc2, &Mutex);
ObReferenceObjectByHandle(hThread[0], THREAD_ALL_ACCESS, *PsThreadType, KernelMode, &Thread[0], NULL);
ObReferenceObjectByHandle(hThread[1], THREAD_ALL_ACCESS, *PsThreadType, KernelMode, &Thread[1], NULL);
KeWaitForMultipleObjects(2, Thread, WaitAll, Executive, KernelMode, FALSE, NULL, NULL);
ObDereferenceObject(Thread[0]);
ObDereferenceObject(Thread[1]);
KdPrint(("主线程结束\n"));
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath
)
{
KdPrint(("hello driver\n"));
DriverObject->DriverUnload = Unload;
MutexTest();
return STATUS_SUCCESS;
}
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/39bbd187f81629960c582be775e76f99.png)
其他内核同步要素
服务函数 | 描述 |
---|
ExAcquireFastMutex() | 获取快速互斥,如果必要则等待 |
ExAcquireFastMutexUnsafe() | 获取快速互斥,如果必要则等待,调用者必须先停止接受APC |
ExInitializeFastMutex() | 初始化快速互斥对象 |
ExReleaseFastMutex() | 释放快速互斥 |
ExReleaseFastMutexUnsafe() | 释放快速互斥 ,不解除APC提交禁止 |
ExTryToAcquireFastMutex() | 获取快速互斥,如果可能,立即获取不等待 |
快速互斥器
#include <ntddk.h>
VOID Unload(IN PDRIVER_OBJECT pDriverObject)
{
KdPrint(("Goodbye driver\n"));
}
VOID ThreadProc1(PVOID Context)
{
LARGE_INTEGER timeout;
timeout.QuadPart = -10 * 2000 * 1000;
PFAST_MUTEX pFastMutex = (PFAST_MUTEX)Context;
ExAcquireFastMutex(pFastMutex);
KdPrint(("进入线程1\n"));
KeDelayExecutionThread(KernelMode, FALSE, &timeout);
KdPrint(("离开线程1\n"));
ExReleaseFastMutex(pFastMutex);
PsTerminateSystemThread(0);
}
VOID ThreadProc2(PVOID Context)
{
LARGE_INTEGER timeout;
timeout.QuadPart = -10 * 2000 * 1000;
PFAST_MUTEX pFastMutex = (PFAST_MUTEX)Context;
ExAcquireFastMutex(pFastMutex);
KdPrint(("进入线程2\n"));
KeDelayExecutionThread(KernelMode, FALSE, &timeout);
KdPrint(("离开线程2\n"));
ExReleaseFastMutex(pFastMutex);
PsTerminateSystemThread(0);
}
VOID FastMutexTest()
{
FAST_MUTEX FastMutex;
HANDLE hThread1, hThread2;
PETHREAD Thread[2] = { NULL };
ExInitializeFastMutex(&FastMutex);
PsCreateSystemThread(&hThread1, THREAD_ALL_ACCESS, NULL, NULL, NULL, ThreadProc1, &FastMutex);
PsCreateSystemThread(&hThread2, THREAD_ALL_ACCESS, NULL, NULL, NULL, ThreadProc2, &FastMutex);
ObReferenceObjectByHandle(hThread1, THREAD_ALL_ACCESS, *PsThreadType, KernelMode, &Thread[0], NULL);
ObReferenceObjectByHandle(hThread2, THREAD_ALL_ACCESS, *PsThreadType, KernelMode, &Thread[1], NULL);
KeWaitForMultipleObjects(2, Thread, WaitAll, Executive, KernelMode, FALSE, NULL, NULL);
ObDereferenceObject(Thread[0]);
ObDereferenceObject(Thread[1]);
KdPrint(("主线程结束\n"));
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath
)
{
KdPrint(("hello driver\n"));
DriverObject->DriverUnload = Unload;
FastMutexTest();
return STATUS_SUCCESS;
}
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/d4a7835c29ecb9badcb90a5d16837bbe.png)
原子集操作
服务函数 | 描述 |
---|
InterlockedCompareExchange | 比较并有条件地交换两个值 |
InterlockedDecrement | 整数减1 |
InterlockedExchange | 交换两个值 |
InterlockedExchangeAdd | 加两个值并返回原始值 |
InterlockedIncrement | 整数加1 |
ExInterlockedAddLargeInteger | 向64位整数数加 |
ExInterlockedAddLargeStatistic | 向ULONG加 |
ExInterlockedAddUlong | 向ULONG加并返回原始值 |
ExInterlockedCompareExchange64 | 交换两个64位置 |
VOID Unload(IN PDRIVER_OBJECT pDriverObject)
{
KdPrint(("Goodbye driver\n"));
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath
)
{
KdPrint(("hello driver\n"));
DriverObject->DriverUnload = Unload;
LONG Value = 10;
InterlockedCompareExchange(&Value, 100, 10);
KdPrint(("InterlockedCompareExchange(&Value, 100, 10):%d\n",Value));
InterlockedDecrement(&Value);
KdPrint(("InterlockedDecrement(&Value):%d\n", Value));
InterlockedExchange(&Value,55);
KdPrint(("InterlockedExchange(&Value,55):%d\n", Value));
KdPrint(("返回原始值:%d\n", InterlockedExchangeAdd(&Value, 1)));
KdPrint(("InterlockedExchangeAdd(&Value, 1):%d\n", Value));
InterlockedIncrement(&Value);
KdPrint(("InterlockedIncrement(&Value):%d\n", Value));
LARGE_INTEGER liValue;
liValue.QuadPart = 10;
LARGE_INTEGER liIncre;
liIncre.QuadPart = 900;
KSPIN_LOCK spinLock;
LONGLONG value1 = 1, value2 = 2, value3 = 3 ;
KdPrint(("***************************"));
KeInitializeSpinLock(&spinLock);
ExInterlockedAddLargeInteger(&liValue, liIncre, &spinLock);
KdPrint(("InterlockedIncrement:%d\n", liValue.LowPart));
ExInterlockedAddLargeStatistic(&liValue,9);
KdPrint(("ExInterlockedAddLargeStatistic:%d\n", liValue.LowPart));
ExInterlockedAddUlong(&Value, 10, &spinLock);
KdPrint(("Exchange64:%d\n", Value));
ExInterlockedCompareExchange64(&value1, &value2, &value3, &spinLock);
KdPrint(("Exchange64:%d\n", value1));
return STATUS_SUCCESS;
}
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/77fe7d6d0ad6f0798009ef70adfbdbb4.png)