提到自旋锁那就必须要说链表,在上一篇《驱动开发:内核中的链表与结构体》
文章中简单实用链表结构来存储进程信息列表,相信读者应该已经理解了内核链表的基本使用,本篇文章将讲解自旋锁的简单应用,自旋锁是为了解决内核链表读写时存在线程同步问题,解决多线程同步问题必须要用锁,通常使用自旋锁,自旋锁是内核中提供的一种高IRQL锁,用同步以及独占的方式访问某个资源。
首先以简单的链表为案例,链表主要分为单向链表与双向链表,单向链表的链表节点中只有一个链表指针,其指向后一个链表元素,而双向链表节点中有两个链表节点指针,其中Blink
指向前一个链表节点Flink
指向后一个节点,以双向链表为例。
#include <ntifs.h> #include <ntstrsafe.h>
typedef struct _MyStruct { ULONG x; ULONG y; LIST_ENTRY lpListEntry; }MyStruct,*pMyStruct;
VOID UnDriver(PDRIVER_OBJECT driver) { DbgPrint("驱动卸载成功 \n"); }
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath) { DbgPrint("By:LyShark \n"); DbgPrint("Email:me@lyshark.com \n"); LIST_ENTRY ListHeader = { 0 }; InitializeListHead(&ListHeader);
MyStruct testA = { 0 }; MyStruct testB = { 0 }; MyStruct testC = { 0 };
testA.x = 100; testA.y = 200;
testB.x = 1000; testB.y = 2000;
testC.x = 10000; testC.y = 20000;
InsertHeadList(&ListHeader, &testA.lpListEntry); InsertTailList(&ListHeader, &testB.lpListEntry); InsertTailList(&ListHeader, &testC.lpListEntry);
if (IsListEmpty(&ListHeader) == FALSE) { RemoveEntryList(&testA.lpListEntry); }
PLIST_ENTRY pListEntry = NULL; pListEntry = ListHeader.Flink;
while (pListEntry != &ListHeader) { pMyStruct ptr = CONTAINING_RECORD(pListEntry, MyStruct, lpListEntry); DbgPrint("节点元素X = %d 节点元素Y = %d \n", ptr->x, ptr->y);
pListEntry = pListEntry->Flink; }
Driver->DriverUnload = UnDriver; return STATUS_SUCCESS; }
|
链表输出效果如下:

如上所述,内核链表读写时存在线程同步问题,解决多线程同步问题必须要用锁,通常使用自旋锁,自旋锁是内核中提供的一种高IRQL锁,用同步以及独占的方式访问某个资源。
#include <ntifs.h> #include <ntstrsafe.h>
typedef struct _MyStruct { ULONG x; ULONG y; LIST_ENTRY lpListEntry; }MyStruct, *pMyStruct;
LIST_ENTRY my_list_header; KSPIN_LOCK my_list_lock;
void Init() { InitializeListHead(&my_list_header); KeInitializeSpinLock(&my_list_lock); }
void function_ins() { KIRQL Irql;
KeAcquireSpinLock(&my_list_lock, &Irql);
DbgPrint("锁内部执行 \n");
KeReleaseSpinLock(&my_list_lock, Irql); }
VOID UnDriver(PDRIVER_OBJECT driver) { DbgPrint("驱动卸载成功 \n"); }
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath) { DbgPrint("By:LyShark \n"); DbgPrint("Email:me@lyshark.com \n");
Init();
pMyStruct testA = (pMyStruct)ExAllocatePool(NonPagedPoolExecute, sizeof(pMyStruct)); pMyStruct testB = (pMyStruct)ExAllocatePool(NonPagedPoolExecute, sizeof(pMyStruct));
testA->x = 100; testA->y = 200;
testB->x = 1000; testB->y = 2000;
if (NULL != testA && NULL != testB) { ExInterlockedInsertHeadList(&my_list_header, (PLIST_ENTRY)&testA->lpListEntry, &my_list_lock); ExInterlockedInsertTailList(&my_list_header, (PLIST_ENTRY)&testB->lpListEntry, &my_list_lock); }
function_ins();
PLIST_ENTRY remove_entry = ExInterlockedRemoveHeadList(&testA->lpListEntry, &my_list_lock);
while (remove_entry != &my_list_header) { pMyStruct ptr = CONTAINING_RECORD(remove_entry, MyStruct, lpListEntry); DbgPrint("节点元素X = %d 节点元素Y = %d \n", ptr->x, ptr->y);
remove_entry = remove_entry->Flink; }
Driver->DriverUnload = UnDriver; return STATUS_SUCCESS; }
|
加锁后执行效果如下:
