内核双向循环链表介绍
来源:互联网 发布:行最简形矩阵的特点 编辑:程序博客网 时间:2024/06/09 19:33
前言
linux内核通常使用一个名字为(struct list_head)的结构体来实现双向循环链表。struct list_head数据结构如下:
struct list_head { struct list_head *next, *prev;};
在需要构造双向循环链表的数据结构中加入(struct list_head)成员,然后通过该成员将数据结构连接成双向循环链表。定位时首先找到struct list_head,然后使用container_of找到整个数据结构的起始地址。
1、常用操作函数介绍
(1)初始化链表头,初始化完后,prev和next指针都指向自己。
/*静态初始化*/#define LIST_HEAD_INIT(name) { &(name), &(name) }#define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name)
/*动态初始化*/static inline void INIT_LIST_HEAD(struct list_head *list){ list->next = list; list->prev = list;}
(2)查找结点。list_for_each用来遍历链表,list_entry用来获取数据结构的起始地址,然后我们就可以判断该结点是不是我们要查找的了。
#define list_entry(ptr, type, member) \ container_of(ptr, type, member)#define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next)#define list_for_each_r(pos, head) \ for (pos = (head)->prev; pos != (head); pos = pos->prev)
(3)添加结点
static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next){ next->prev = new; new->next = next; new->prev = prev; prev->next = new;}static inline void list_add(struct list_head *new, struct list_head *head){ __list_add(new, head, head->next);}static inline void list_add_tail(struct list_head *new, struct list_head *head){ __list_add(new, head->prev, head);}
(4)删除结点
static inline void __list_del(struct list_head * prev, struct list_head * next){ next->prev = prev; prev->next = next;}static inline void list_del(struct list_head *entry){ __list_del(entry->prev, entry->next); entry->next = LIST_POISON1; entry->prev = LIST_POISON2;}
(5)判断链表是否为空
static inline int list_empty(const struct list_head *head){ return head->next == head;}
(6)合并两个链表
static inline void __list_splice(struct list_head *list, struct list_head *head){ struct list_head *first = list->next; struct list_head *last = list->prev; struct list_head *at = head->next; first->prev = head; head->next = first; last->next = at; at->prev = last;}static inline void list_splice(struct list_head *list, struct list_head *head){ if (!list_empty(list)) __list_splice(list, head);}
2、使用例子
int main(void) { struct list_head head, *plist; struct student *node; INIT_LIST_HEAD(&head); list_add(&stu[0].list, &head); list_add(&stu[1].list, &head); list_add(&stu[2].list, &head); list_add(&stu[3].list, &head); list_add(&stu[4].list, &head); list_for_each(plist, &head) { node = list_entry(plist, struct student, list); print_message(node); } return 0;}
0 0
- 内核双向循环链表介绍
- 内核双向循环链表
- 内核双向循环链表之旅
- linux内核双向循环链表实例
- 内核双向循环链表之旅
- Linux内核双向循环链表分析
- 内核数据结构之双向循环链表
- 通用链表(内核双向循环链表list_head)
- Linux内核-双向循环链表代码分析
- 详解Linux内核之双向循环链表(转载)
- 详解Linux内核之双向循环链表
- 详解Linux内核之双向循环链表(转)
- linux内核的数据结构:1 双向循环链表
- 详解Linux内核之双向循环链表
- 详解Linux内核之双向循环链表(一)
- 详解Linux内核之双向循环链表(二)
- 详解Linux内核之双向循环链表
- 详解Linux内核之双向循环链表 .
- POSTMAN的安装
- noConflict()
- mysql查询字段值为空的记录
- Java判断String是否是中文,并把中文转换成Unicode
- Perl学习(十二)——数组定义操作总结
- 内核双向循环链表介绍
- com.ibatis.sqlmap.engine.builder.xml.SqlMapConfigParser
- C++ using namespace 命名空间
- obs-studio中自定义信号(signal)
- RecyclerView三种布局下的上拉加载 下拉刷新
- JZOJ4857. Tourist Attractions
- maven构建spring mvc + spring data jpa+ sql server 配置
- 继承派生优缺点小议
- Halcon 算子 读写图像