链表之类的结构总是涉及多线程,这时候就要用到使用锁。
当然在处理临界区的时候,这个是必须要考虑的呀。
在驱动开发的代码中,大多是在于多线程执行环境的。
下面将介绍使用简单的自旋锁。
如下的代码将初始化一个自旋锁:
KSPIN_ my_Spin_Lock; KeInitializeSpinLock(&my_Spin_Lock);KeInitializeSpinLock 函数没有返回值。
在KeAccquireSpinLock 和 KeReleaseSpinLock 之间的代码是只有单线程执行的,其他的现成会停留在KeAccquireSpinLock 等候,直到KeReleaseSpinLock被调用。KIRQL是一个中断级。
void MySafeFunction() { KSPIN_LOCK my_spin_lock; KIRQL irql; KeInitialiezeSpinLock(&my_spin_lock); KeAccquireSpinLock(&my_spin_lock, &irql); //----do something KeReleaseSpinLock(&my_spin_lock, &irql); }(怎么和 函数: waitforsingleObject 的使用非常相似呢?
在堆栈中,每个线程都会重新初始化一个锁,只有所有的线程共用一个锁,锁才意义。锁一般不会定义成局部变量。
LIT_ENTRY 有一系列的操作。这些操作并不需要使用者自己调用获取与释放锁,只需要为每个链表定并初始化一个锁即可。
LIST_ENTRY my_List_Head; ///---链表头 KSPIN_LOCK my_spin_lock; ///--链表的锁 ///--链表初始化函数 void MyFileInfoInit() { InitializeListHead(&my_List_Head); KeAccquireSpinLock(&my_spin_lock); }初始化就这样简单的完成了。接下来就可以采用加锁的操作来代替普通的操作啦:
////-----插入一个节点。
普通操作代码:
InsertHeadList(&my_spin_lock, (PLIST_ENTRY)&my_File_Info);换成加锁的代码如下:
ExIntertlockedInsetHeadList( &my_List_Head, (PLIST_ENTRY)&my_File_Info, &my_spin_lock );不同在于增加了 KSPIN_LOCK 的指针作为参数。在函数 ExIntertInsertHeadList 中,会自动使用 这个 KSPIN_LOCK进行加锁。类似的还有一个加锁函数 Remove 函数。用来移除一个节点:
///------移除节点代码
my_file_info = ExInterlockedRemoveHeadList( &my_list_head, &my_list_lock );----------------------- 摘自<[天书夜读-从汇编到Windows内核编程]>