将单向链表排序迁移到驱动层, 验证通过(组合: (升序/降序) *(链表回环/非回环))
如果算法实现需要确认, 还是在应用层先验证完, 再迁入驱动层好些. 能节省大量时间.
迁移(应用层 => 驱动层)过程中的修改点:
结构 的new delete => lookasidelist 的 alloc free
随机数 Srand(), Rand() => KeQuerySystemTime, RtlRandomEx
工程下载:srcListSortOnDrv.rar
在驱动层中的排序效果:
>> DriverEntry on 1353 >> TestListSort nTryIndex = 1 TestListSort(LISTNODE_CNT, IS_LIST_LOOP_NOT, SORT_BY_SMALL_TO_BIG); uSeed = 0, sort = small to big ListSort Before ======================================== ShowList >> ======================================== Head[0x8B662E00], Head.pNext[0x903157B0], Head.data[0x26ff8a4f] Node[0x903157B0], Node.pNext[0x9506C2A8], Node.data[0x3967c02d] Node[0x9506C2A8], Node.pNext[0x95119988], Node.data[0x1a2b995c] Node[0x95119988], Node.pNext[0x980B18A0], Node.data[0x4c576173] Node[0x980B18A0], Node.pNext[0x8B66BA78], Node.data[0x17d78f8e] Node[0x8B66BA78], Node.pNext[0x00000000], Node.data[0x39e8ed02] ListSort After ======================================== ShowList >> ======================================== Head[0x980B18A0], Head.pNext[0x9506C2A8], Head.data[0x17d78f8e] Node[0x9506C2A8], Node.pNext[0x8B662E00], Node.data[0x1a2b995c] Node[0x8B662E00], Node.pNext[0x903157B0], Node.data[0x26ff8a4f] Node[0x903157B0], Node.pNext[0x8B66BA78], Node.data[0x3967c02d] Node[0x8B66BA78], Node.pNext[0x95119988], Node.data[0x39e8ed02] Node[0x95119988], Node.pNext[0x00000000], Node.data[0x4c576173] TestListSort(LISTNODE_CNT, IS_LIST_LOOP_NOT, SORT_BY_BIG_TO_SMALL); uSeed = 913725478, sort = big to small ListSort Before ======================================== ShowList >> ======================================== Head[0x903157B0], Head.pNext[0x8B662E00], Head.data[0x5735c79b] Node[0x8B662E00], Node.pNext[0x9506C2A8], Node.data[0x056cc5e9] Node[0x9506C2A8], Node.pNext[0x83A7DC00], Node.data[0x1510ddff] Node[0x83A7DC00], Node.pNext[0x950A73E8], Node.data[0x5a43d391] Node[0x950A73E8], Node.pNext[0x950B2048], Node.data[0x7034ca46] Node[0x950B2048], Node.pNext[0x00000000], Node.data[0x6b9ff85a] ListSort After ======================================== ShowList >> ======================================== Head[0x950A73E8], Head.pNext[0x950B2048], Head.data[0x7034ca46] Node[0x950B2048], Node.pNext[0x83A7DC00], Node.data[0x6b9ff85a] Node[0x83A7DC00], Node.pNext[0x903157B0], Node.data[0x5a43d391] Node[0x903157B0], Node.pNext[0x9506C2A8], Node.data[0x5735c79b] Node[0x9506C2A8], Node.pNext[0x8B662E00], Node.data[0x1510ddff] Node[0x8B662E00], Node.pNext[0x00000000], Node.data[0x056cc5e9] TestListSort(LISTNODE_CNT, IS_LIST_LOOP, SORT_BY_SMALL_TO_BIG); uSeed = 1412756275, sort = small to big ListSort Before ======================================== ShowList >> ======================================== Head[0x903157B0], Head.pNext[0x83A7DC00], Head.data[0x6ec0894e] Node[0x83A7DC00], Node.pNext[0x950B2048], Node.data[0x0f4736c3] Node[0x950B2048], Node.pNext[0x8B663B60], Node.data[0x7391e7d3] Node[0x8B663B60], Node.pNext[0x9034E4C8], Node.data[0x30519197] Node[0x9034E4C8], Node.pNext[0x8B654E30], Node.data[0x58d66ac7] Node[0x8B654E30], Node.pNext[0x903157B0], Node.data[0x129d2a65] ListSort After ======================================== ShowList >> ======================================== Head[0x83A7DC00], Head.pNext[0x8B654E30], Head.data[0x0f4736c3] Node[0x8B654E30], Node.pNext[0x8B663B60], Node.data[0x129d2a65] Node[0x8B663B60], Node.pNext[0x9034E4C8], Node.data[0x30519197] Node[0x9034E4C8], Node.pNext[0x903157B0], Node.data[0x58d66ac7] Node[0x903157B0], Node.pNext[0x950B2048], Node.data[0x6ec0894e] Node[0x950B2048], Node.pNext[0x83A7DC00], Node.data[0x7391e7d3] TestListSort(LISTNODE_CNT, IS_LIST_LOOP, SORT_BY_BIG_TO_SMALL); uSeed = 1765149990, sort = big to small ListSort Before ======================================== ShowList >> ======================================== Head[0x9034E4C8], Head.pNext[0x8B663B60], Head.data[0x4b89b0c9] Node[0x8B663B60], Node.pNext[0x8B654E30], Node.data[0x1a43c31f] Node[0x8B654E30], Node.pNext[0x8B630678], Node.data[0x30180ee2] Node[0x8B630678], Node.pNext[0x903157B0], Node.data[0x65a6e602] Node[0x903157B0], Node.pNext[0x8B65C3C0], Node.data[0x76ad2254] Node[0x8B65C3C0], Node.pNext[0x9034E4C8], Node.data[0x5fbdb2dd] ListSort After ======================================== ShowList >> ======================================== Head[0x903157B0], Head.pNext[0x8B630678], Head.data[0x76ad2254] Node[0x8B630678], Node.pNext[0x8B65C3C0], Node.data[0x65a6e602] Node[0x8B65C3C0], Node.pNext[0x9034E4C8], Node.data[0x5fbdb2dd] Node[0x9034E4C8], Node.pNext[0x8B654E30], Node.data[0x4b89b0c9] Node[0x8B654E30], Node.pNext[0x8B663B60], Node.data[0x30180ee2] Node[0x8B663B60], Node.pNext[0x903157B0], Node.data[0x1a43c31f]
/// @file sys.c /// @brief 驱动主程序 #include "Function.h" #define MODULE_NAME L"DrvDemo" #define DRIVER_NAME MODULE_NAME L".sys" #define DEVICE_NAME_GLOBAL L"\\\\.\\" MODULE_NAME #define DEVICE_NAME L"\\device\\" MODULE_NAME #define LINK_NAME L"\\dosDevices\\" MODULE_NAME /// 测试单向链表排序 #define LISTNODE_CNT 6 ///< 单向链表节点数量 #define IS_LIST_LOOP TRUE ///< 单向链表是否回环, 是 #define IS_LIST_LOOP_NOT FALSE ///< 单向链表是否回环, 否 #define SORT_BY_SMALL_TO_BIG TRUE ///< 排序方式, 升序 #define SORT_BY_BIG_TO_SMALL FALSE ///< 排序方式, 降序 #define TEST_LIST_SORT_CNT 10 ///< 测试ListSort的次数 extern LARGE_INTEGER g_liSeed; NTSTATUS DispatchCommon(PDEVICE_OBJECT pDeviceObject, PIRP pIrp); VOID DriverUnload(PDRIVER_OBJECT pDriverObject); /// 测试单向链表排序 void TestCaseListSort(); void TestListSort(size_t nListNodeCnt, BOOL bIsListLoop, BOOL bSortBySmallToBig); NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegPath) { size_t nIndex = 0; NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_OBJECT pDeviceObject = NULL; UNICODE_STRING ustrDeviceName = {0}; UNICODE_STRING ustrLinkName = {0}; DbgPrint(">> DriverEntry on 1353\r\n"); g_liSeed.QuadPart = 0; ///< 初始化随机种子 RtlInitUnicodeString(&ustrDeviceName, DEVICE_NAME); RtlInitUnicodeString(&ustrLinkName, LINK_NAME); ntStatus = IoCreateDevice( pDriverObject, 0, &ustrDeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject); if (!NT_SUCCESS(ntStatus)) { DbgPrint("<< DriverEntry : error IoCreateDevice\r\n"); return ntStatus; } pDeviceObject->Flags |= DO_BUFFERED_IO; ntStatus = IoCreateSymbolicLink( &ustrLinkName, &ustrDeviceName); if (!NT_SUCCESS(ntStatus)) { DbgPrint("<< DriverEntry : error IoDeleteDevice\r\n"); IoDeleteDevice(pDeviceObject); return ntStatus; } for(nIndex = 0; nIndex < IRP_MJ_MAXIMUM_FUNCTION; nIndex++) { pDriverObject->MajorFunction[nIndex] = DispatchCommon; } pDriverObject->DriverUnload = DriverUnload; ListNodeDataInit(); TestCaseListSort(); ///< 测试链表排序(回环, 非回环, 降序, 升序) ListNodeDataUnInit(); DbgPrint("<< DriverEntry\r\n"); return STATUS_SUCCESS; } void TestCaseListSort() { size_t nTryIndex = 0; size_t nTryCnt = TEST_LIST_SORT_CNT; DbgPrint(">> TestListSort\r\n"); g_liSeed.QuadPart = 0; ///< 随机种子清零 do { DbgPrint("\r\n\r\nnTryIndex = %d\r\n", ++nTryIndex); DbgPrint("\r\n\r\nTestListSort(LISTNODE_CNT, IS_LIST_LOOP_NOT, " "SORT_BY_SMALL_TO_BIG);\r\n"); TestListSort(LISTNODE_CNT, IS_LIST_LOOP_NOT, SORT_BY_SMALL_TO_BIG); DbgPrint("\r\n\r\nTestListSort(LISTNODE_CNT, IS_LIST_LOOP_NOT, " "SORT_BY_BIG_TO_SMALL);\r\n"); TestListSort(LISTNODE_CNT, IS_LIST_LOOP_NOT, SORT_BY_BIG_TO_SMALL); DbgPrint("\r\n\r\nTestListSort(LISTNODE_CNT, IS_LIST_LOOP, " "SORT_BY_SMALL_TO_BIG);\r\n"); TestListSort(LISTNODE_CNT, IS_LIST_LOOP, SORT_BY_SMALL_TO_BIG); DbgPrint("\r\n\r\nTestListSort(LISTNODE_CNT, IS_LIST_LOOP, " "SORT_BY_BIG_TO_SMALL);\r\n"); TestListSort(LISTNODE_CNT, IS_LIST_LOOP, SORT_BY_BIG_TO_SMALL); } while (nTryCnt-- > 0); DbgPrint("<< TestListSort\r\n"); } void TestListSort(size_t nListNodeCnt, BOOL bIsListLoop, BOOL bSortBySmallToBig) { PNODE pNode = NULL; DbgPrint("uSeed = %d, sort = %s\r\n", g_liSeed.LowPart, bSortBySmallToBig ? "small to big" : "big to small"); /// 初始化链表数据 /// 建立链表(节点数量, 是否回环) ListCreate(&pNode, nListNodeCnt, bIsListLoop); DbgPrint("ListSort Before\r\n"); ListShow(&pNode); /// 单向链表排序 ListSort(&pNode, bSortBySmallToBig); DbgPrint("ListSort After\r\n"); ListShow(&pNode); /// 释放链表 ListRemove(&pNode); /// 反初始化链表数据 } VOID DriverUnload(PDRIVER_OBJECT pDriverObject) { UNICODE_STRING ustrLinkName = {0}; DbgPrint(">> DriverUnload\r\n"); RtlInitUnicodeString(&ustrLinkName, LINK_NAME); IoDeleteDevice(pDriverObject->DeviceObject); IoDeleteSymbolicLink(&ustrLinkName); DbgPrint("<< DriverUnload\r\n"); } NTSTATUS DispatchCommon(PDEVICE_OBJECT pDeviceObject, PIRP pIrp) { pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; }
/// @file Function.h /// @brief 功能的实现 #ifndef __FUNCTION_H__ #define __FUNCTION_H__ /// ntddk.h 和 Ntifs.h 不能同时包含如果不行, 需要拷贝没有的定义过来 // #include <ntddk.h> #include <Ntifs.h> ///< for RtlRandomEx #include <WINDEF.H> // for warning C4996: 'ExAllocatePool': was declared deprecated #pragma warning(disable:4996) // #define DEBUG_SHOW_LIST ///< 打印中间调试过程的单向链表 #define MEM_TYPE_NODE 'NODE' ///< 节点类型的内存 typedef struct _node { int data; struct _node * pNext; } NODE,*PNODE; /// 链表数据初始化与反初始化 /// 原因: 分配节点时, 要从lookasideList中分配空间 void ListNodeDataInit(); void ListNodeDataUnInit(); /// 外部接口 /// @fn ListSort /// @brief 链表排序 /// @param PNODE * ppNodeHead, 单向链表头指针, 支持回环单向链表 /// @param BOOL bSortBySmallToBig, TRUE, 从小到大排序; FALSE, 从大到小排序 BOOL ListSort(PNODE * ppNodeHead, BOOL bSortBySmallToBig); /// 内部接口 /// @fn ListNodeSwap /// @brief 交换2个节点(节点本身, 父节点, 子节点) /// @param PNODE * ppNodeCur, 当前节点 /// @param PNODE * ppNodeCurParent, 当前节点的父节点 /// @param PNODE * ppNodeReplace, 要交换的节点 /// @param PNODE * ppNodeReplaceParent, 要交换的节点的父节点 BOOL ListNodeSwap(PNODE * ppNodeCur, PNODE * ppNodeCurParent, PNODE * ppNodeReplace, PNODE * ppNodeReplaceParent); /// @fn CreateList /// @brief 建立一个单向链表 /// @param PNODE * ppNode, 链表首节点指针, *ppNode 必须为空 /// @param size_t nListSize, 链表的元素个数 /// @param BOOL bIsListLoop, 是否创建单回环链表, 如果是, 该链表首尾相接 void ListCreate(PNODE * ppNode, size_t nListSize, BOOL bIsListLoop); void ListNodeCreate(PNODE * ppNode); void ListNodeFree(PNODE * ppNode); void ListRemove(PNODE * ppNode); void ListShow(PNODE * ppNode); /// @fn IsListLoop /// @brief 链表是否回环 /// @param IN PNODE * ppNodeHead, 单向链表头指针 /// @param OUT size_t * pnElementsCnt, 单向链表的元素计数 /// @param OUT PNODE * ppNodeTail, 单向链表尾指针 /// @return BOOL /// @retval TRUE, 链表回环 /// @retval FALSE, 不是回环链表 /// @note OUT size_t & nElementsCnt 编译不过 ? BOOL IsListLoop(IN PNODE * ppNodeHead, OUT size_t * pnElementsCnt, OUT PNODE * ppNodeTail); /// @fn GenerateRand /// @param 产生一个在uMin~ulMax之间的随机数 ULONG GenerateRand(ULONG ulMin, ULONG ulMax); #endif
/// @file Function.c /// @brief 功能的实现 #include "Function.h" #include "LookasideListOpt.h" LARGE_INTEGER g_liSeed; ULONG GenerateRand(ULONG ulMin, ULONG ulMax) { /// 浮点运算在内核编程中不被支持, 可以定义DWORD值来解决 ULONG ulRand = 0; ULONG ulRange = 0; ULONG ulMinReal = min(ulMax, ulMin); ULONG ulMaxReal = max(ulMax, ulMin); ULONGLONG ullTmp = 0; if (0 == g_liSeed.QuadPart) KeQuerySystemTime(&g_liSeed); g_liSeed.QuadPart++; ///< 每次的种子都不同 ulRand = RtlRandomEx(&(g_liSeed.LowPart)); ullTmp = ulRand; ullTmp = ullTmp * (ulMaxReal - ulMinReal); return (ULONG)((ullTmp / MAXLONG) + ulMinReal); } /// 为Node节点分配空间的LookasideList PAGED_LOOKASIDE_LIST g_PageLookasideList_Node; PAGED_LOOKASIDE_LIST * g_pPageLookasideList_Node = &g_PageLookasideList_Node; void ListNodeDataInit() { LookasideListInit(TRUE, &g_pPageLookasideList_Node, sizeof(NODE)); } void ListNodeDataUnInit() { LookasideListDelete(TRUE, &g_pPageLookasideList_Node); } void ListNodeCreate(PNODE * ppNode) { PNODE pNode = NULL; NT_ASSERT(NULL != ppNode); if (!NT_SUCCESS(LookasideListAllocate(TRUE, g_pPageLookasideList_Node, &pNode))) { DbgPrint("LookasideListAllocate(TRUE) error\r\n"); *ppNode = NULL; } else { *ppNode = pNode; } NT_ASSERT(NULL != *ppNode); (*ppNode)->data = GenerateRand(1, MAXLONG); ///< 结点的数据是随机的 (*ppNode)->pNext = NULL; } void ListNodeFree(PNODE * ppNode) { if ((NULL != ppNode) && (NULL != *ppNode)) { if (!NT_SUCCESS(LookasideListFree(TRUE, g_pPageLookasideList_Node, ppNode))) { DbgPrint("LookasideListFree(TRUE) error\r\n"); } *ppNode = NULL; } } void ListCreate(PNODE * ppNode, size_t nListSize, BOOL bIsListLoop) { PNODE pNodeHead = NULL; PNODE pNodeCur = NULL; size_t nIndex = 0; if ((NULL == ppNode) || (NULL != *ppNode) || (nListSize < 1)) return; ListNodeCreate(&pNodeHead); *ppNode = pNodeHead; pNodeCur = pNodeHead; for (nIndex = 1; nIndex < nListSize; nIndex++) { ListNodeCreate(&pNodeCur->pNext); pNodeCur = pNodeCur->pNext; } if (bIsListLoop) pNodeCur->pNext = pNodeHead; ///< 形成单链表回环 } void ListShow(PNODE * ppNode) { PNODE pNodeCur = NULL; PNODE pNodeHead = NULL; DbgPrint("========================================\r\n"); DbgPrint("ShowList >>\r\n"); DbgPrint("========================================\r\n"); if ((NULL == ppNode) || (NULL == *ppNode)) { DbgPrint("ppNode is invalid\n"); return; } pNodeHead = *ppNode; DbgPrint("Head[0x%p], Head.pNext[0x%p], Head.data[0x%8.8x]\n", pNodeHead, pNodeHead->pNext, pNodeHead->data); pNodeCur = pNodeHead->pNext; while ((NULL != pNodeCur) && (pNodeCur != pNodeHead)) { DbgPrint("Node[0x%p], Node.pNext[0x%p], Node.data[0x%8.8x]\n", pNodeCur, pNodeCur->pNext, pNodeCur->data); pNodeCur = pNodeCur->pNext; } } void ListRemove(PNODE * ppNode) { PNODE pNodeHead = NULL; PNODE pNodeCur = NULL; PNODE pNodeNext = NULL; if ((NULL == ppNode) || (NULL == *ppNode)) { return; } pNodeHead = *ppNode; /// 释放头节点之外的数据 pNodeCur = pNodeHead->pNext; while ((NULL != pNodeCur) && (pNodeCur != pNodeHead)) { pNodeNext = pNodeCur->pNext; ListNodeFree(&pNodeCur); pNodeCur = pNodeNext; } /// 释放头节点 ListNodeFree(&pNodeHead); *ppNode = NULL; } BOOL IsListLoop(IN PNODE * ppNodeHead, OUT size_t * pnElementsCnt, OUT PNODE * ppNodeTail) { BOOL bFind = FALSE; PNODE pNodeCur = NULL; PNODE pNodeHead = NULL; NT_ASSERT(NULL != ppNodeHead); NT_ASSERT(NULL != *ppNodeHead); NT_ASSERT(NULL != pnElementsCnt); NT_ASSERT(NULL != ppNodeTail); pNodeHead = *ppNodeHead; pNodeCur = pNodeHead->pNext; *ppNodeTail = pNodeCur; (*pnElementsCnt)++; while (NULL != pNodeCur) { if (pNodeCur == pNodeHead) { bFind = TRUE; break; } *ppNodeTail = pNodeCur; pNodeCur = pNodeCur->pNext; (*pnElementsCnt)++; } return bFind; } BOOL ListSort(PNODE * ppNodeHead, BOOL bSortBySmallToBig) { BOOL bListIsLoop = FALSE; ///< 链表是否回环 /// 是否需要修复链表尾部Next指针(当链表头被移动后) BOOL bNeedFixListTail = FALSE; /// 节点交换是否成功, 如果是相同节点, 不需要交换 BOOL bListNodeSwapOK = FALSE; size_t nElementsCnt = 0; ///< 链表元素个数 PNODE pNodeTail = NULL; ///< 链表尾节点 PNODE pNodeCur = NULL; ///< 当前节点 PNODE pNodeCurParent = NULL; ///< pNodeCur节点的父节点 /// 需要交换的节点, 根据bSortBySmallToBig标志可能为最小值节点或最大值节点 PNODE pNodeReplace = NULL; PNODE pNodeReplaceParent = NULL; ///< pNodeReplace节点的父节点 PNODE pNodeNext = NULL; ///< 下一个节点 PNODE pNodeNextParent = NULL; ///< pNodeNext节点的父节点 /// 临时链表头, 使原始链表有父节点, 为了防止节点size过大, 需要new出来 PNODE pNodeHeadTmp = NULL; NT_ASSERT(NULL != ppNodeHead); NT_ASSERT(NULL != *ppNodeHead); /// 不关心链表是否回环, 只需要链表元素个数 bListIsLoop = IsListLoop(ppNodeHead, &nElementsCnt, &pNodeTail); if (nElementsCnt <= 1) return TRUE; ///< 链表节点2个以上, 才需要排序 /// 加入临时链表头, 使链表头指针有父节点 ListNodeCreate(&pNodeHeadTmp); pNodeHeadTmp->pNext = *ppNodeHead; ///< 链表头指针 /// 每个节点都记录父节点和子节点, 用于节点插入法排序 /// 排序, 小的节点在前 pNodeCurParent = pNodeHeadTmp; for (pNodeCur = pNodeHeadTmp->pNext; ; pNodeCur = pNodeCur->pNext) { if ((NULL == pNodeCur) || (pNodeCur == pNodeTail)) break; ///< 放在for循环条件中不行? pNodeReplace = pNodeCur; pNodeNextParent = pNodeCur; for (pNodeNext = pNodeCur->pNext; ; pNodeNext = pNodeNext->pNext) { if ((NULL == pNodeNext) || (pNodeNext == pNodeHeadTmp->pNext)) break; ///< 放在for循环条件中不行? if (bSortBySmallToBig ? (pNodeNext->data < pNodeReplace->data) : (pNodeNext->data > pNodeReplace->data)) { pNodeReplace = pNodeNext; ///< 找到了需要交换的节点 /// 为了交换节点, 需要记录该节点的父节点 pNodeReplaceParent = pNodeNextParent; } pNodeNextParent = pNodeNext; } bNeedFixListTail = bListIsLoop && (pNodeCur == pNodeHeadTmp->pNext); bListNodeSwapOK = ListNodeSwap(&pNodeCur, &pNodeCurParent, &pNodeReplace, &pNodeReplaceParent); if (bListNodeSwapOK && bNeedFixListTail) { /// 对于回环情况的链表尾部节点, 当被交换的节点涉及到首节点时, /// 链表尾部节点->pNext应重新设置成首节点 /// 求链表尾部节点 bListIsLoop = IsListLoop(ppNodeHead, &nElementsCnt, &pNodeTail); pNodeTail->pNext = pNodeHeadTmp->pNext; } #ifdef DEBUG_SHOW_LIST if (bListNodeSwapOK) { /// 测试用, 每交换一次节点, 就打印一次 ListShow(&pNodeHeadTmp->pNext); } #endif pNodeCurParent = pNodeCur; ///< 记录当前节点的父节点 } /// 在替换链表节点过程中, 链表首节点已经变了 /// pNodeHeadTmp->pNext 一直指向的是真正的链表头 *ppNodeHead = pNodeHeadTmp->pNext; ///< 设置真正的链表头 /// 释放临时链表头 ListNodeFree(&pNodeHeadTmp); return TRUE; } BOOL ListNodeSwap(PNODE * ppNodeCur, PNODE * ppNodeCurParent, PNODE * ppNodeReplace, PNODE * ppNodeReplaceParent) { PNODE pNodeCur = NULL; PNODE pNodeCurParent = NULL; ///< 当前节点的父节点 PNODE pNodeReplace = NULL; PNODE pNodeReplaceParent = NULL; ///< pNodeReplace节点的父节点 PNODE pNodeTmp = NULL; ///< 临时节点指针, 用于交换节点指针 NT_ASSERT(NULL != ppNodeCur); NT_ASSERT(NULL != ppNodeCurParent); NT_ASSERT(NULL != ppNodeReplace); NT_ASSERT(NULL != ppNodeReplaceParent); pNodeCur = *ppNodeCur; pNodeCurParent = *ppNodeCurParent; pNodeReplace = *ppNodeReplace; pNodeReplaceParent = *ppNodeReplaceParent; if (pNodeReplace != pNodeCur) { /// 用插入法交换pNodeCur和pNodeReplace(节点本身指针, 父节点,子节点) /// 将pNodeReplace放到pNodeCur原来的位置 pNodeCurParent->pNext = pNodeReplace; pNodeTmp = pNodeReplace->pNext; if (pNodeCur->pNext != pNodeReplace) { /// 如果两个节点不相邻, /// 交换后, 最小值节点的下一个节点是是pNodeCur的下一个节点 pNodeReplace->pNext = pNodeCur->pNext; } else { /// 这种情况下, pNodeCur的下一个节点是pNodeReplace /// 交换后, pNodeReplace->pNext 应该直接指向 pNodeCur pNodeReplace->pNext = pNodeCur; } /// 将pNodeCur放到pNodeReplace原来的位置 pNodeReplaceParent->pNext = pNodeCur; pNodeCur->pNext = pNodeTmp; /// 使交换后的pNodeCur为pNodeReplace, 保证可以继续查找值 /// 否则: 数据在链表尾部, 导致交换节点后, 不能再继续查找值 /// ! pNodeReplaceParent->pNext 指的的原来的 pNodeReplace 节点 *ppNodeCur = pNodeReplace; return TRUE; } else return FALSE; }
/// @file LookasideListOpt.h /// @brief LookasideList 封装 #ifndef __LOOK_A_SIDE_LIST_OPT_H__ #define __LOOK_A_SIDE_LIST_OPT_H__ #include <ntddk.h> #include <WINDEF.H> /// operate LookasideList #define LOOK_A_SIDE_LIST_POOL_TAG_NAME 'lasl' ///< 内存分配标记 /// @fn LookasideListInit /// @brief 初始化LookAsideList /// @param BOOLEAN bpage, TRUE = 分页内存, FALSE = 非分页内存 /// @param void ** ppLookAsideList, ppLookAsideList2级指针, 函数内部用到的 /// 时候强转类型 /// @param size_t nBufSize, 每次从LookAsideList中可以分配的内存大小 /// @return NTSTATUS, 调用方使用 NT_SUCCESS 宏来判断是否成功 NTSTATUS LookasideListInit(BOOLEAN bpage, void ** ppLookAsideList, size_t nBufSize); /// @fn LookasideListAllocate /// @param 从LookAsideList中分配一块内存 /// @param BOOLEAN bpage, TRUE = 分页内存, FALSE = 非分页内存 /// @param void ** ppLookAsideList, ppLookAsideList2级指针, 函数内部用到的 /// 时候强转类型 /// @param void ** ppNodeOut, 传出分配后的内存2级指针 /// @return NTSTATUS, 调用方使用 NT_SUCCESS 宏来判断是否成功 NTSTATUS LookasideListAllocate(BOOLEAN bpage, void * pLookAsideList, void ** ppNodeOut); /// @fn LookasideListFree /// @param 从LookAsideList中释放一块内存 /// @param BOOLEAN bpage, TRUE = 分页内存, FALSE = 非分页内存 /// @param void ** ppLookAsideList, ppLookAsideList2级指针, 函数内部用到的 /// 时候强转类型 /// @param void ** ppNodeOut, 曾经分配好的的内存2级指针 /// @return NTSTATUS, 调用方使用 NT_SUCCESS 宏来判断是否成功 NTSTATUS LookasideListFree(BOOLEAN bpage, void * pLookAsideList, void ** ppNodeOut); /// @fn LookasideListDelete /// @brief 释放LookasideList /// @param BOOLEAN bpage, TRUE = 分页内存, FALSE = 非分页内存 /// @return NTSTATUS, 调用方使用 NT_SUCCESS 宏来判断是否成功 NTSTATUS LookasideListDelete(BOOLEAN bpage, void ** ppLookAsideList); /// 内部函数 NTSTATUS LookasideListInit_Page(void ** ppLookAsideList, size_t nBufSize); NTSTATUS LookasideListInit_NPage(void ** ppLookAsideList, size_t nBufSize); NTSTATUS LookasideListAllocate_Page(void * pLookAsideList, void ** ppNodeOut); NTSTATUS LookasideListAllocate_NPage(void * pLookAsideList, void ** ppNodeOut); NTSTATUS LookasideListFree_Page(void * pLookAsideList, void ** ppNodeOut); NTSTATUS LookasideListFree_NPage(void * pLookAsideList, void ** ppNodeOut); NTSTATUS LookasideListDelete_Page(void ** ppLookAsideList); NTSTATUS LookasideListDelete_NPage(void ** ppLookAsideList); #endif // #ifndef __LOOK_A_SIDE_LIST_OPT_H__
/// @file LookasideListOpt.c /// @brief ... #include "LookasideListOpt.h" NTSTATUS LookasideListInit(BOOLEAN bpage, void ** ppLookAsideList, size_t nBufSize) { if (NULL == ppLookAsideList) return STATUS_INVALID_PARAMETER; if (bpage) return LookasideListInit_Page(ppLookAsideList, nBufSize); else return LookasideListInit_NPage(ppLookAsideList, nBufSize); } NTSTATUS LookasideListAllocate(BOOLEAN bpage, void * pLookAsideList, void ** ppNodeOut) { if ((NULL == pLookAsideList) || (NULL == ppNodeOut)) return STATUS_INVALID_PARAMETER; if (bpage) return LookasideListAllocate_Page(pLookAsideList, ppNodeOut); else return LookasideListAllocate_NPage(pLookAsideList, ppNodeOut); } NTSTATUS LookasideListFree(BOOLEAN bpage, void * pLookAsideList, void ** ppNodeOut) { if ((NULL == pLookAsideList) || (NULL == ppNodeOut) || (NULL == *ppNodeOut)) return STATUS_INVALID_PARAMETER; if (bpage) return LookasideListFree_Page(pLookAsideList, ppNodeOut); else return LookasideListFree_NPage(pLookAsideList, ppNodeOut); } NTSTATUS LookasideListDelete(BOOLEAN bpage, void ** ppLookAsideList) { if ((NULL == ppLookAsideList) || (NULL == *ppLookAsideList)) return STATUS_INVALID_PARAMETER; if (bpage) return LookasideListDelete_Page(ppLookAsideList); else return LookasideListDelete_NPage(ppLookAsideList); } ////////////////////////////////////////////////////////////////////////// /// 内部函数 ////////////////////////////////////////////////////////////////////////// NTSTATUS LookasideListInit_Page(void ** ppLookAsideList, size_t nBufSize) { PPAGED_LOOKASIDE_LIST pLookaside = NULL;; NT_ASSERT(NULL != ppLookAsideList); NT_ASSERT(NULL != *ppLookAsideList); PAGED_CODE(); pLookaside = *((PAGED_LOOKASIDE_LIST **)ppLookAsideList); ExInitializePagedLookasideList(pLookaside, NULL, NULL, 0, nBufSize, LOOK_A_SIDE_LIST_POOL_TAG_NAME, 0 ); *ppLookAsideList = pLookaside; return (NULL != pLookaside) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; } NTSTATUS LookasideListInit_NPage(void ** ppLookAsideList, size_t nBufSize) { PNPAGED_LOOKASIDE_LIST pLookaside = NULL; NT_ASSERT(NULL != ppLookAsideList); NT_ASSERT(NULL != *ppLookAsideList); pLookaside = *((NPAGED_LOOKASIDE_LIST **)ppLookAsideList); ExInitializeNPagedLookasideList(pLookaside, NULL, NULL, 0, nBufSize, LOOK_A_SIDE_LIST_POOL_TAG_NAME, 0 ); *ppLookAsideList = pLookaside; return (NULL != pLookaside) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; } NTSTATUS LookasideListAllocate_Page(void * pLookAsideList, void ** ppNodeOut) { PAGED_CODE(); *ppNodeOut = ExAllocateFromPagedLookasideList( (PPAGED_LOOKASIDE_LIST)pLookAsideList); return (NULL != *ppNodeOut) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; } NTSTATUS LookasideListAllocate_NPage(void * pLookAsideList, void ** ppNodeOut) { *ppNodeOut = ExAllocateFromNPagedLookasideList( (PNPAGED_LOOKASIDE_LIST)pLookAsideList); return (NULL != *ppNodeOut) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; } NTSTATUS LookasideListFree_Page(void * pLookAsideList, void ** ppNodeOut) { PAGED_CODE(); ExFreeToPagedLookasideList((PPAGED_LOOKASIDE_LIST)pLookAsideList, *ppNodeOut); *ppNodeOut = NULL; return STATUS_SUCCESS; } NTSTATUS LookasideListFree_NPage(void * pLookAsideList, void ** ppNodeOut) { ExFreeToNPagedLookasideList((PNPAGED_LOOKASIDE_LIST)pLookAsideList, *ppNodeOut); *ppNodeOut = NULL; return STATUS_SUCCESS; } NTSTATUS LookasideListDelete_Page(void ** ppLookAsideList) { PPAGED_LOOKASIDE_LIST pLookAsideList = *ppLookAsideList; PAGED_CODE(); ExDeletePagedLookasideList(pLookAsideList); *ppLookAsideList = NULL; return STATUS_SUCCESS; } NTSTATUS LookasideListDelete_NPage(void ** ppLookAsideList) { PNPAGED_LOOKASIDE_LIST pLookAsideList = *ppLookAsideList; ExDeleteNPagedLookasideList(pLookAsideList); *ppLookAsideList = NULL; return STATUS_SUCCESS; }