詳解C語(yǔ)言內(nèi)核中的自旋鎖結(jié)構(gòu)
提到自旋鎖那就必須要說(shuō)鏈表,在上一篇《驅(qū)動(dòng)開(kāi)發(fā):內(nèi)核中的鏈表與結(jié)構(gòu)體》文章中簡(jiǎn)單實(shí)用鏈表結(jié)構(gòu)來(lái)存儲(chǔ)進(jìn)程信息列表,相信讀者應(yīng)該已經(jīng)理解了內(nèi)核鏈表的基本使用,本篇文章將講解自旋鎖的簡(jiǎn)單應(yīng)用,自旋鎖是為了解決內(nèi)核鏈表讀寫時(shí)存在線程同步問(wèn)題,解決多線程同步問(wèn)題必須要用鎖,通常使用自旋鎖,自旋鎖是內(nèi)核中提供的一種高IRQL鎖,用同步以及獨(dú)占的方式訪問(wèn)某個(gè)資源。
首先以簡(jiǎn)單的鏈表為案例,鏈表主要分為單向鏈表與雙向鏈表,單向鏈表的鏈表節(jié)點(diǎn)中只有一個(gè)鏈表指針,其指向后一個(gè)鏈表元素,而雙向鏈表節(jié)點(diǎn)中有兩個(gè)鏈表節(jié)點(diǎn)指針,其中Blink
指向前一個(gè)鏈表節(jié)點(diǎn)Flink
指向后一個(gè)節(jié)點(diǎn),以雙向鏈表為例。
#include <ntifs.h> #include <ntstrsafe.h> /* // 鏈表節(jié)點(diǎn)指針 typedef struct _LIST_ENTRY { struct _LIST_ENTRY *Flink; // 當(dāng)前節(jié)點(diǎn)的后一個(gè)節(jié)點(diǎn) struct _LIST_ENTRY *Blink; // 當(dāng)前節(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn) }LIST_ENTRY, *PLIST_ENTRY; */ typedef struct _MyStruct { ULONG x; ULONG y; LIST_ENTRY lpListEntry; }MyStruct,*pMyStruct; VOID UnDriver(PDRIVER_OBJECT driver) { DbgPrint("驅(qū)動(dòng)卸載成功 \n"); } // By: LyShark NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath) { DbgPrint("By:LyShark \n"); DbgPrint("Email:me@lyshark.com \n"); // 初始化頭節(jié)點(diǎ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; // 分別插入節(jié)點(diǎn)到頭部和尾部 InsertHeadList(&ListHeader, &testA.lpListEntry); InsertTailList(&ListHeader, &testB.lpListEntry); InsertTailList(&ListHeader, &testC.lpListEntry); // 節(jié)點(diǎn)不為空 則 移除一個(gè)節(jié)點(diǎn) if (IsListEmpty(&ListHeader) == FALSE) { RemoveEntryList(&testA.lpListEntry); } // 輸出鏈表數(shù)據(jù) PLIST_ENTRY pListEntry = NULL; pListEntry = ListHeader.Flink; while (pListEntry != &ListHeader) { // 計(jì)算出成員距離結(jié)構(gòu)體頂部?jī)?nèi)存距離 pMyStruct ptr = CONTAINING_RECORD(pListEntry, MyStruct, lpListEntry); DbgPrint("節(jié)點(diǎn)元素X = %d 節(jié)點(diǎn)元素Y = %d \n", ptr->x, ptr->y); // 得到下一個(gè)元素地址 pListEntry = pListEntry->Flink; } Driver->DriverUnload = UnDriver; return STATUS_SUCCESS; }
鏈表輸出效果如下:
如上所述,內(nèi)核鏈表讀寫時(shí)存在線程同步問(wèn)題,解決多線程同步問(wèn)題必須要用鎖,通常使用自旋鎖,自旋鎖是內(nèi)核中提供的一種高IRQL鎖,用同步以及獨(dú)占的方式訪問(wèn)某個(gè)資源。
#include <ntifs.h> #include <ntstrsafe.h> /* // 鏈表節(jié)點(diǎn)指針 typedef struct _LIST_ENTRY { struct _LIST_ENTRY *Flink; // 當(dāng)前節(jié)點(diǎn)的后一個(gè)節(jié)點(diǎn) struct _LIST_ENTRY *Blink; // 當(dāng)前節(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn) }LIST_ENTRY, *PLIST_ENTRY; */ 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); } // 函數(shù)內(nèi)使用鎖 void function_ins() { KIRQL Irql; // 加鎖 KeAcquireSpinLock(&my_list_lock, &Irql); DbgPrint("鎖內(nèi)部執(zhí)行 \n"); // 釋放鎖 KeReleaseSpinLock(&my_list_lock, Irql); } VOID UnDriver(PDRIVER_OBJECT driver) { DbgPrint("驅(qū)動(dòng)卸載成功 \n"); } // By: LyShark 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; // 向全局鏈表中插入數(shù)據(jù) 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(); // 移除節(jié)點(diǎn)A并放入到remove_entry中 PLIST_ENTRY remove_entry = ExInterlockedRemoveHeadList(&testA->lpListEntry, &my_list_lock); // 輸出鏈表數(shù)據(jù) while (remove_entry != &my_list_header) { // 計(jì)算出成員距離結(jié)構(gòu)體頂部?jī)?nèi)存距離 pMyStruct ptr = CONTAINING_RECORD(remove_entry, MyStruct, lpListEntry); DbgPrint("節(jié)點(diǎn)元素X = %d 節(jié)點(diǎn)元素Y = %d \n", ptr->x, ptr->y); // 得到下一個(gè)元素地址 remove_entry = remove_entry->Flink; } Driver->DriverUnload = UnDriver; return STATUS_SUCCESS; }
加鎖后執(zhí)行效果如下:
到此這篇關(guān)于詳解C語(yǔ)言內(nèi)核中的自旋鎖結(jié)構(gòu)的文章就介紹到這了,更多相關(guān)C語(yǔ)言內(nèi)核 自旋鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單反彈球消磚塊游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單反彈球消磚塊游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05C/C++?string.h庫(kù)中memcpy()和memmove()的使用
memcpy與memmove的目的都是將N個(gè)字節(jié)的源內(nèi)存地址的內(nèi)容拷貝到目標(biāo)內(nèi)存地址中,本文主要介紹了C/C++?string.h庫(kù)中memcpy()和memmove()的使用,感興趣的可以了解一下2023-12-12C語(yǔ)言實(shí)現(xiàn)的階乘,排列和組合實(shí)例
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)的階乘,排列和組合的方法,涉及C語(yǔ)言數(shù)學(xué)運(yùn)算的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07詳解C++中的vector容器及用迭代器訪問(wèn)vector的方法
使用迭代器iterator可以更方便地解引用和訪問(wèn)成員,當(dāng)然也包括vector中的元素,本文就來(lái)詳解C++中的vector容器及用迭代器訪問(wèn)vector的方法,需要的朋友可以參考下2016-05-05