[学习笔记][图解]链表结构——双向循环链表

今天在研究内核层通过PEB取程序模块地址时遇到了这个双链表结构,因为接触链表不多,所以一开始自己给理解蒙了,后来一顿查资料+问大佬,理清楚了这个逻辑,作下笔记,谨防忘记。

回到正题,PEB结构里面有很多成员,很多成员及其子成员都有定义为 LIST_ENTRY 这个结构,跳转看了下。

typedef struct _LIST_ENTRY {
   struct _LIST_ENTRY *Flink;
   struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;

嗯,明显的链表结构,之前看meng老师教程看到过,大概理解了下就直接抄走了,现在该自己写了,也不想翻以前抄的源码,没想到以为理解透彻了的思路竟然还很混乱。

其中 FLINK 表示 下一节点,BLINK 表示 前一节点,也可以分别叫做,后继和前驱。链表基本有链表头和链表尾,但是遍历链表时一般不需要知道真正的头尾是哪个,只需要把你第一个遍历的节点,看做表头,然后定义一个变量记录下这个“假表头”,循环时每次都判断一下,如果在循环中遇到有节点的Next=我们记录的这个表头,那么这个节点,就是“假表尾”,代表我们已经成功的遍历完一遍链表了。

然后,就是让我这个萌新有点想不懂的地方来了。

为什么 FLINK 和 BLINK 的类型是他自身呢?如果这样成立,为什么不会出现死循环内存溢出呢?

道理很简单,图中已经画的很明显了,这种双向循环链表,其实就是 结构中包含结构。

这样的做法,就可以实现让 FLINK 或 BLINK 走起来,而不是固定的一个值或者用其他线程去控制,这样麻烦的东西。

至于为什么不会造成内存溢出,玄机就在于循环的实现,在真正的表尾处的 FLINK = 真正的表头处的 BLINK。

双向循环链表大概就这么多知识。

单向循环链表呢,等我接触时,或者有空再画图和笔记一篇。

使用双向链表的好处很多,比如遍历链表,我们可以从任意节点开始走 FLINK 或 BLINK 看个人喜好,不需要管真正的表头和表尾,我们都能将这个链表完整的遍历一遍。

但是插入节点就相对于单向链表复杂那么一丢丢,不过具体也没去了解,毕竟自己没接触到,看其他博客大佬们说的。

然后本文部分为自己的理解,如果有误,欢迎在评论指点。谢谢。

(来自一位强迫症患者自述:刚开始自己理解时用的微软自带的画图,理解完后准备画一张标准的图发博客用,然后微软的画图画不了箭头,于是一顿搜下载了 AutoCAD,下载后发现并不像PS那么会玩,于是乎又卸载了,最后还是用PS画的这张图,画的时间没多久,几个小时全他妈做其他破事浪费了)

(参考资料:https://blog.csdn.net/baweiyaoji/article/details/76071053)

猜你喜欢

转载自blog.csdn.net/u012088909/article/details/80710804