自旋锁,简单来说就是防止多线程并发导致的错误。我们加锁后,那么当另外一个线程尝试去访问,发现已经被其他锁占用了,那么此线程就会等待锁结束后再去访问。
使用方法:
1.自旋锁初始化
2.在锁开始和结束的中间,写入需要锁住的代码
以下是示例代码:
KSPIN_LOCK MySpinLock;//锁一般不会定义成局部变量,否则没有意义
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING Reg) {
//自旋锁初始化
KeInitializeSpinLock(&MySpinLock);
KIRQL irql;
KeAcquireSpinLock(&MySpinLock,&irql);//加锁开启
//这里写需要被加锁保护的代码
KeReleaseSpinLock(&MySpinLock, irql);//加锁结束
DriverObject->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
上面是一段简单的自旋锁代码,那么对于双向链表来说,肯定也是需要自旋锁的。
官方提供了自旋锁链表操作的相关函数,以下为示例代码:
typedef struct _Test {
ULONG Data;
LIST_ENTRY ListEntry;
KSPIN_LOCK SpinLock;
}Test,*PTest;
KSPIN_LOCK MySpinLock = { 0 };
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING Reg) {
/*
在双向链表中使用自旋锁:
直接使用自旋锁自带的链表操作即可完成链表的:插入,移除
*/
Test A = { 0 };
Test B = { 0 };
Test C = { 0 };
A.Data = 'A';
B.Data = 'B';
C.Data = 'C';
//初始化链表和锁
LIST_ENTRY MyListEntry = { 0 };
InitializeListHead(&MyListEntry);
KeInitializeSpinLock(&MySpinLock);
//在自旋锁在干预下执行插入
ExInterlockedInsertHeadList(&MyListEntry, &B.ListEntry, &MySpinLock);
ExInterlockedInsertHeadList(&MyListEntry, &A.ListEntry, &MySpinLock);
ExInterlockedInsertTailList(&MyListEntry, &C.ListEntry, &MySpinLock);
//到此为止,双向链表为 头 A B C
//接下来移除第一个节点
//在自旋锁的干预下执行移除
ExInterlockedRemoveHeadList(&MyListEntry, &MySpinLock);
//如果要移除任意指定节点,请手动使用其他链表操作函数,手动上锁。
//--------------------链表的遍历--------------------
//双向链表-从前向后遍历
KdPrint(("------------------------------------\n"));
PLIST_ENTRY PListEntry = NULL;//定义一个指针链表
PListEntry = MyListEntry.Flink;//因为是从前往后遍历,所以让它等于前部
while (PListEntry != &MyListEntry) {
PTest PTestListEntry = CONTAINING_RECORD(PListEntry, Test, ListEntry);//使用一个宏把ListEntry成员转换为结构体Test的首地址
DbgPrint("PListEntry=%p PTestListEntry=%p data=%c\n", PListEntry, PTestListEntry, (CHAR)PTestListEntry->Data);
//上面输出完毕,接下来指向下一个节点的前部,因为这里PListEntry是一个指针,所以他和ListHeader是同步的,是可修改的,获取的直接是地址。
PListEntry = PListEntry->Flink;
}
DriverObject->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
根据上面的代码,我们发现,对于双向链表的自旋锁操作,也非常简单。步骤如下:
1.初始化自旋锁——KeInitializeSpinLock
2.插入链表——ExInterlockedInsertHeadList或ExInterlockedInsertTailList
3.移除链表——ExInterlockedRemoveHeadList
标签: WINDOWS内核编程