1.自己实现内核链表的部分
2.内核链表使用举例
#include <stdio.h>
struct list_head
{
struct list_head * prev;
struct list_head * next;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
/*
1.向链表中添加节点,普通的在两个非空结点中插入一个结点,注意new、prev、next都不能是空值
2.Prev可以等于next,此时在只含头节点的链表中插入新节点。
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_head(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_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
prev->next = next;
}
//删除entry所指的结点,同时将entry所指向的结点指针域封死
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = NULL;
entry->prev = NULL;
}
//移动节点
//将entry所指向的结点移动到head所指向的结点的后面。
static inline void list_move_head(struct list_head *entry, struct list_head *head)
{
__list_del(entry->prev, entry->next);
list_add_head(entry, head);
}
//删除了list所指向的结点,将其插入到head所指向的结点的前面,
//如果head->prev指向链表的尾结点的话,就是将list所指向的结点插入到链表的结尾
static inline void list_move_tail(struct list_head *entry, struct list_head *head)
{
__list_del(entry->prev, entry->next);
list_add_tail(entry, head);
}
//判断是否为空链表
//由list-head构成的双向循环链表中,通常有一个头节点,其不含有有效信息,
//初始化时prev和next都指向自身。判空操作是判断除了头节点外是否有其他节点。
//试链表是否为空,如果是只有一个结点,head,head->next,head->prev都指向同一个结点,则这里会返回1,
//表示空;但这个空不是没有任何结点,
//而是只有一个头结点,因为头节点只是纯粹的list节点,没有有效信息,故认为为空
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
static inline int list_empty_careful(const struct list_head *head)
{
struct list_head *next = head->next;
return (next == head) && (next == head->prev);
}
//链表合并
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);
}
/*
作用:找到成员与结构体开始地址的偏移
TYPE:大结构体的类型
MEMBER:大结构体中成员的名称
*/
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
/*
作用:通过成员的指针找到大结构体的指针
ptr 结构体成员的指针
type 大结构体的类型
member ptr代表的成员在大结构体的名称
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
//链表遍历
#define __list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
/*
pos:大结构体的指针
head:头结点
member: struct list_head 在大结构体中的名称
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
//相比于list_for_each_entry,list_for_each_entry_safe用指针n对链表的下一个数据结构进行了临时存储,
//所以如果在遍历链表的时候需要做删除链表中的当前项操作时,用list_for_each_entry_safe可以安全的删除,
//而不会影响接下来的遍历过程(用n指针可以继续完成接下来的遍历, 而list_for_each_entry则无法继续遍历,
//删除后会导致无法继续遍历)
/*
pos:大结构体的指针
n:大结构体的指针,是一个备份
head:头结点
member: struct list_head 在大结构体中的名称
*/
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
struct student
{
int id;
int age;
struct list_head entry;
};
int main(int argc, char const *argv[])
{
struct student * pos_st = NULL;
struct student * pos_n = NULL;
LIST_HEAD(list_head_obj);//struct list_head list_head_obj = {&list_head_obj, &list_head_obj};
struct student STA = {0, 21, {NULL, NULL}};
struct student STB = {1, 22, {NULL, NULL}};
struct student STC = {2, 23, {NULL, NULL}};
struct student STD = {4, 66, {NULL, NULL}};
list_add_tail(&STA.entry, &list_head_obj);
list_add_tail(&STB.entry, &list_head_obj);
list_add_tail(&STC.entry, &list_head_obj);
list_add_head(&STD.entry, &list_head_obj);
list_for_each_entry(pos_st, &list_head_obj, entry)
{
printf("id:[%d] age[%d]\n", pos_st->id, pos_st->age);
}
list_for_each_entry_safe(pos_st, pos_n, &list_head_obj, entry)
{
printf("id:[%d] age[%d]\n", pos_st->id, pos_st->age);
}
return 0;
}
部分资源来源于网络,若有侵权,请联系作者删除。