Linux内核中的链表

要使用内核链表,需要包含头文件<linux/list.h>,链表结构定义如下:

struct list_head {
	struct list_head *next, *prev;
};

Linux内核中的链表是一个双向循环链表,结构中只包含两个指针next和prev,不包含其它任何数据成员,同常见定义链表稍有不同。在Linux内核中使用链表,是将链表内嵌在其它结构体中来使用,从这里也可以看出,Linux内核虽然使用c语言这种非面向对象语言,但也体现出了面向对象的思想(继承)。
例如:

struct todo_struct {
	struct list_head list;
	int priority; /* driver specific */
	/* ... add other driver-specific fields */
};


1. 链表头
链表头通常需要单独维护,例如:

struct list_head todo_list;
定义了一个链表头todo_list,在使用之前,需要使用宏INIT_LIST_HEAD对链表头做初始化:
INIT_LIST_HEAD(&todo_list);

当然,Linux内核也提供了一个宏用于静态定义一个链表头并对其做初始化:
LIST_HEAD(todo_list);
实际展开后如下:
struct list_head todo_list = { &todo_list, &todo_list };
所谓初始化就是让链表中的next、prev指针同时指向自己。

2. list_add和list_add_tail
list_add和list_add_tail函数都是将一个节点添加到链表上,只是list_add是表头处,list_add_tail是表尾,函数原型如下:
void list_add(struct list_head *new, struct list_head *head);
void list_add_tail(struct list_head *new, struct list_head *head);
当然这个头并不是绝对意义上的链表头,也可以是链表中的其它节点,表示在该节点之后或之前插入一个新节点。

3. list_del
删除链表中的节点(指删除entry节点),原型如下:
void list_del(struct list_head *entry); 

4. list_empty
判断链表是否为空,原型如下:
int list_empty(const struct list_head *head);

5. list_splice
通过在head之后插入一个新链表来合并两个链表,原型如下:
void list_splice(const struct list_head *list, struct list_head *head);

6. list_for_each、list_for_each_safe、list_for_each_prev和list_for_each_prev_safe
遍历链表,list_for_each是从头开始遍历,而list_for_each_prev是从尾部开始遍历,加safe字段表示如果循环中可能会删除链表中的节点,就应该使用这些函数。

7. list_entry
链表始终是内嵌在其它结构体当中来使用的,但是从前面的API来看,我们最多只能得到链表中的节点,那么如何得到整个大结构体的指针呢,那就需要使用到这里的宏list_entry,例如:

void todo_add_entry(struct todo_struct *new)
{
	struct list_head *ptr;
	struct todo_struct *entry;

	list_for_each(ptr, &todo_list) {
		entry = list_entry(ptr, struct todo_struct, list);
		if (entry->priority < new->priority) {
			list_add_tail(&new->list, ptr);
			return;
		}
	}
	list_add_tail(&new->list, &todo_struct);
}
list_entry定义有三个参数,第一个参数是struct list_head类型的指针,第二个参数是包含这个struct list_head成员的结构体类型,例如前面的struct todo_struct,第三个参数是结构体中该struct list_head的名字。

8. list_for_each_entry、list_for_each_entry_safe
使用这两个宏的话,就不用在list_for_each中调用list_entry宏。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值