linux链表list_head的基本原理及使用

1、list_head结构原型

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

此结构体构成的链表为双向循环链表。该结构体在linux内核中被大量引用,几乎所有内核当中需要构成链表结构的地方都用到了这个结构体。例如内核的总线设备就用到了这个结构体。

2、头结点的创建及初始化

struct list_head head ={
    &(head),&(head)
};

链表初始化时,head结构体的成员指向自己。如下图所示:

 

3、链表的添加过程

list_add(struct list_head *_new, struct list_head *prev,
    struct list_head *next)
{
	next->prev = _new;  // 1
	_new->next = next;  // 2
	_new->prev = prev;  // 3
	prev->next = _new;  // 4
}

其中_new为新添加的结点,prev和next为头结点的两个成员,进行如上四步操作完成链表的添加,如下图所示:

4、链表的使用方法

        该结构体只有纯粹的链表指针成员,不能直接用来链接数据。所以需要在其它结构体中加入该链表结构体,才能发挥该链表的作用。该链表可作为各种不同数据结构体的成员,也就是说它能将多种数据结构链接在一起,使用非常灵活。

        那么如何通过链表指针来得到某个结点上的数据呢?

扫描二维码关注公众号,回复: 4616189 查看本文章

        它是通过container_of宏,获得所在结点的结构体指针,再通过结构体指针来访问对应结点的数据的。

5、container_of 宏

container_of宏的作用为:知道结构体变量中某一个变量,用来反推这个结构体变量的指针。

其定义为:

#define container_of(ptr, type, member)                                      \
({                                                                           \
    const typeof(((type *) NULL)->member) *__mptr = (ptr);              \
    (type *) ((char *) __mptr - offsetof(type, member));                \
})

其实现可分为两个部分:

第一部分:   const  typeof(((type *) NULL)->member) * __mptr = (ptr); 

        通过typeof定义一个member指针类型的指针变量__mptr,(即__mptr是指向member类型的指针),并将__mptr赋值为ptr。

第二部分:   (type *) ((char *) __mptr - offsetof(type, member));    

       通过offsetof宏计算出member在type中的偏移,然后用member的实际地址__mptr减去偏移量,即可得到type的起始地址,即指向type类型的指针。

6、linux_list.h的使用

如下头文件,包含了对链表的一些基本操作,都是通过内联函数或者宏来实现的,可直接包含后使用。

#ifndef _LINUX_LIST_H_
#define _LINUX_LIST_H_

#include <stddef.h>
#include <stdbool.h>

#define	prefetch(x)

#ifndef container_of
#define container_of(ptr, type, member)					\
	({								\
		const typeof(((type *) NULL)->member) *__mptr = (ptr);	\
		(type *) ((char *) __mptr - offsetof(type, member));	\
	})
#endif

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

#define LIST_HEAD_INIT(name) { &(name), &(name) }
#undef LIST_HEAD
#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->prev = list;
}
//判断这个链表是否为空
static inline bool
list_empty(const struct list_head *head)
{
	return (head->next == head);
}
//判断该结点是否为头结点
static inline bool
list_is_first(const struct list_head *list,
	      const struct list_head *head)
{
	return list->prev == head;
}
//判断该结点是否为尾结点
static inline bool
list_is_last(const struct list_head *list,
	     const struct list_head *head)
{
	return list->next == head;
}

static inline void
_list_del(struct list_head *entry)
{
	entry->next->prev = entry->prev;
	entry->prev->next = entry->next;
}
//删除结点
static inline void
list_del(struct list_head *entry)
{
	_list_del(entry);
	entry->next = entry->prev = NULL;
}
//添加结点
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_del_init(struct list_head *entry)
{
	_list_del(entry);
	INIT_LIST_HEAD(entry);
}

#define	list_entry(ptr, type, field)	container_of(ptr, type, field)
#define	list_first_entry(ptr, type, field)	list_entry((ptr)->next, type, field)
#define	list_last_entry(ptr, type, field)	list_entry((ptr)->prev, type, field)

//从前到后遍历链表
#define	list_for_each(p, head)						\
	for (p = (head)->next; p != (head); p = p->next)
//删除当前结点不会造成断链
#define	list_for_each_safe(p, n, head)					\
	for (p = (head)->next, n = p->next; p != (head); p = n, n = p->next)
//遍历链表上的结构体
#define list_for_each_entry(p, h, field)				\
	for (p = list_first_entry(h, typeof(*p), field); &p->field != (h); \
	    p = list_entry(p->field.next, typeof(*p), field))

#define list_for_each_entry_safe(p, n, h, field)			\
	for (p = list_first_entry(h, typeof(*p), field),		\
	    n = list_entry(p->field.next, typeof(*p), field); &p->field != (h);\
	    p = n, n = list_entry(n->field.next, typeof(*n), field))

#define	list_for_each_entry_reverse(p, h, field)			\
	for (p = list_last_entry(h, typeof(*p), field); &p->field != (h); \
	    p = list_entry(p->field.prev, typeof(*p), field))

#define	list_for_each_prev(p, h) for (p = (h)->prev; p != (h); p = p->prev)
#define	list_for_each_prev_safe(p, n, h) for (p = (h)->prev, n = p->prev; p != (h); p = n, n = p->prev)

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);
}

static inline void
list_move(struct list_head *list, struct list_head *head)
{
	_list_del(list);
	list_add(list, head);
}

static inline void
list_move_tail(struct list_head *entry, struct list_head *head)
{
	_list_del(entry);
	list_add_tail(entry, head);
}

static inline void
_list_splice(const struct list_head *list, struct list_head *prev,
    struct list_head *next)
{
	struct list_head *first;
	struct list_head *last;

	if (list_empty(list))
		return;

	first = list->next;
	last = list->prev;
	first->prev = prev;
	prev->next = first;
	last->next = next;
	next->prev = last;
}

static inline void
list_splice(const struct list_head *list, struct list_head *head)
{
	_list_splice(list, head, head->next);
}

static inline void
list_splice_tail(struct list_head *list, struct list_head *head)
{
	_list_splice(list, head->prev, head);
}

static inline void
list_splice_init(struct list_head *list, struct list_head *head)
{
	_list_splice(list, head, head->next);
	INIT_LIST_HEAD(list);
}

static inline void
list_splice_tail_init(struct list_head *list, struct list_head *head)
{
	_list_splice(list, head->prev, head);
	INIT_LIST_HEAD(list);
}

#endif /* _LINUX_LIST_H_ */

猜你喜欢

转载自blog.csdn.net/fangye945a/article/details/85057763