A、链表结构
B、链表的初始化
C、在链表中插入数据(结点)
D、链表数据的删除
E、链表的遍历
课时:19
//链表指针结构
LIST_ENTRY
//初始化链表
InitializeListHead
//判断链表是否为空
IsListEmpty
//在头部插入结点
InsertHeadList
//在尾部插入结点
InsertTailList
//从链表中删除
//头部删除
RemoveHeadList
//尾部删除
RemoveTailList
========================
笔记:
还是继续上节课的双向链表,添加上节课的头文件,将new替换成new(PagedPool),说这个new是我们自己定义的就这样写(我不太明白),再将printf替换成DbgPrint,这样就可以在驱动中使用我们的链表文件头了。将编译的驱动程序放虚拟机里测试一下,用WINDBG或者DebugView查看信息,成功
取得了节点信息。
虽然这种方法是可以的,但是我们在驱动里提供了另外的函数(看教案),然后在文件头中将以前的EXE链表代码修改成驱动代码,也就是用驱动函数替换.
//文件名:Linktype.h
typedef struct _DATA_LINK
{
/*链域,*llink是左链域指针,*rlink是右链域指针*/
//struct _DATA_LINK *L;
//struct _DATA_LINK *R;
LIST_ENTRY Entry;//初始化节点
// struct _DATA_LINK *Head;
int data; /*数据域*/
int data2;
}DATA_LINK,*PDATA_LINK;
//LIST_ENTRY My_List; //自定义链接头
PDATA_LINK head;//=new(PagedPool) DATA_LINK;头节点
PDATA_LINK pData;
VOID Link_Test()
{ KdPrint(("\n-----------SYS模式 双向循环链表测试-------- \n"));
head=new(PagedPool) DATA_LINK;
//初始化链表
//head->L=head->R=head;
//head->Entry.Blink=head->Entry.Flink=&head->Entry;
InitializeListHead(&head->Entry);//指针域
head->data=0;
head->data2=0;
DbgPrint("head=%x\n",head);
//在链表中插入5个元素
DbgPrint(("开始构建链表 \n"));
for (int i=1 ; i<=5 ; i++)
{
pData =new(PagedPool) DATA_LINK;
pData->data = i;
pData->data2= i+1;
InsertHeadList(&head->Entry,&pData->Entry);//插入指针
pData->data-7,pData,pData->R,pData->L,pData->data,pData->data2);
}
//从链表中取出,并显示
DbgPrint("head=%x\n",head);
PDATA_LINK pnode=head;
do //判断 R遍历完成否
{
//显示链表内存结构
DbgPrint("结点%d=%x,R=%x,L=%x,%d,%d\n",
pnode->data,pnode,pnode->Entry.Flink,pnode->Entry.Blink,pnode->data,pnode->data2);//遍历指针代码
pnode=(PDATA_LINK)pnode->Entry.Blink;
} while (!(pnode==head));
}
代码写完后在虚拟机里测试一下,与我们在EXE中执行的结果是一样的.再次加入调试信息测试一下,没发现信息?原来是被挤到后面去了,加入换行就正确了.本节课的测试是非常成功了,这里只讲了常见的链表驱动函数,还有很多函数不懂的可以查阅MSDN. |