描述
在linux内核中封装了一个通用的双向链表库,这个通用的链表库有很好的扩展性和封装性,它给我们提供了一个固定的指针域结构体,我们在使用的时候,只需要在我们定义的数据域结构体中包含这个指针域结构体就可以了,具体的实现、链接并不需要我们关心,只要调用提供给我们的相关接口就可以完成了。
传统的链表结构
1 | 复制代码struct node{ |
linux 内核通用链表库结构
1 | 复制代码提供给我们的指针域结构体: |
可以看到通过这个 list_head
结构就把我们的数据层跟驱动层分开了,而内核提供的各种操作方法接口也只关心 list_head
这个结构,也就是具体链接的时候也只链接这个list_head
结构,并不关心你数据层定义了什么类型.
一些接口宏定义
1 | 复制代码//初始化头指针 |
使用方式
1 | 复制代码typedef struct node{ |
list_add 接口,先入后出原则,有点类似于栈
list_add-先入后出模式
list_add_tail 接口,先入先出原则,有点类似于fifo
list_add-先入先出模式
我们的链表节点,实际在内存中的展示形态
节点描述
可以看到最终的形态是,通过指向每个结构体里面的 list_head
类型指针,然后把它们串联起来的
list_entry 接口,通过结构体变量某个成员的地址,反推结构体首地址,就像 __list_for_each 接口只返回
list_head
地址,所以我们要通过这个成员地址在去获取它本身的结构体首地址,底层实现方法container_of
宏
反推结构体首地址
结束
linux 内核提供的这个通用链表库里面还有很多其他的接口,这里没有详细的一一举例,有兴趣的可以自己去看看,在源码包 include/linux/list.h
文件里面,不过通过阅读一些源代码确实对我们也有很大的提高,可以看看高手是如何去设计并实现,还可以学到一些技巧以及对代码细节的掌握~~.
本文转载自: 掘金