首先,内核链表的头文件,在linux内核的 /include/linux 下的 List.h ,把List.h 复制出来,黏贴到 工程下,就可以直接用内核链表的一些宏和函数。
以下介绍内核链表的一些宏和函数,已经他的实现方式和使用方法。
(1)什么是内核链表:
如图:内核链表一般就是 在一个结构体 有一个结构体成员变量,该结构体成员变量只有 next 和 prev两个指针,分别指向下一个结点和上一个结构,就像一条绳子串起所有的结构体,这样做的好处,就是可以用内核链表来串起各个不同类型的结构体。
(2)内核链表的初始化:
#include "kernel_list.h" //我把内核中的 /include/linux/List.h 改名为 kernel_list.h
#include
struct Person
{
char name[20];
int age;
struct list_head mylist; //其中 list_head 在kernel_list.h 中有定义,这个结构体就只有两个结构体指针(next和prev)
};
int main()
{
struct Person *p;
INIT_LIST_HEAD(&(p->mylist)); //主要是使用 INIT_LIST_HEAD()这个宏初始化那个链表。
return 0;
}
以下是宏INIT_LIST_HEAD()的实现方法,仅作了解就行,因为引入了 /include/linux/List.h 后,是可以直接使用 INIT_LIST_HEAD的
#define INIT_LIST_HEAD(ptr) \ //ptr是指针
do { \
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)
作用是把 指针指向的结构体 中的next和prev都指向自己。
(3)插入内核链表结点:
在结点head之后插入新节点。(这是实现原理,仅作了解就行,后面会有怎么用的代码)
static inline void list_add(struct list_head *new, struct list_head *head) //在结点之后插入新结点
{
__list_add(new, head, head->next); //__list_add()这个函数,等等就讲
}
在结点head之前插入新节点。(这是实现原理,仅作了解就行,后面会有怎么用的代码)
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
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;
}
struct list_head {
struct list_head *next, *prev;
};
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); \
pos = pos->next)
/**
#define list_for_each_prev(pos, head) \
for (pos = (head)->prev; pos != (head); \
pos = pos->prev)
struct student
{
int num;
struct list_head mylist;
};
int show(struct student *head)
{
struct student *pos;
list_for_each_entry(pos,&(head->mylist),mylist) //list_for_each_entry()是将要介绍的宏。
{ //用list_for_each_entry的话,pos可以写你定义的结构体类型(struct student)
printf("pos->num is:%d\n",pos->num); // 而不是struct list_head ,而用list_for_each的话,pos必须是 list_head类型的
}
return 0;
}
#define list_for_each_entry_reverse(pos, head, member) \
for (pos = list_entry((head)->prev, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.prev, typeof(*pos), member))
#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)) //一个for循环
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
这片代码看起来有点难懂,我们来画个图看看:
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = (void *) 0;
entry->prev = (void *) 0;
}
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
next->prev = prev;
prev->next = next;
}
#include
#include
#include "kernel_list.h"
struct student
{
int num;
struct list_head mylist;
};
// 内核链表的初始化
struct student * list_init()
{
struct student *head=malloc(sizeof(struct student));
INIT_LIST_HEAD(&(head->mylist));
return head;
}
// 创建新的节点
struct student * new_node(int data)
{
struct student *new=malloc(sizeof(struct student));
new->num=data;
INIT_LIST_HEAD(&(new->mylist));
return new;
}
// 添加新的节点到内核链表中
int kernellist_add(struct student *new,struct student *head)
{
list_add(&(new->mylist), &(head->mylist));
return 0;
}
// 打印内核链表的数据
int show(struct student *head)
{
struct student *pos;
list_for_each_entry(pos,&(head->mylist),mylist)
{
printf("pos->num is:%d\n",pos->num);
}
return 0;
}
int main()
{
int n;
int i;
struct student *mynewnode;
struct student *p=list_init();
printf("please input num you want create node!\n");
scanf("%d",&n);
for(i=1; i<=n; i++)
{
mynewnode = new_node(i);
kernellist_add(mynewnode,p);
}
show(p);
return 0;
}