赞
踩
首先,内核链表的头文件,在linux内核的 /include/linux 下的 List.h ,把List.h 复制出来,黏贴到 工程下,就可以直接用内核链表的一些宏和函数。
以下介绍内核链表的一些宏和函数,已经他的实现方式和使用方法。
(1)什么是内核链表:
如图:内核链表一般就是 在一个结构体 有一个结构体成员变量,该结构体成员变量只有 next 和 prev两个指针,分别指向下一个结点和上一个结构,就像一条绳子串起所有的结构体,这样做的好处,就是可以用内核链表来串起各个不同类型的结构体。
(2)内核链表的初始化:
- #include "kernel_list.h" //我把内核中的 /include/linux/List.h 改名为 kernel_list.h
- #include <stdio.h>
-
-
- 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 <stdio.h>
- #include <stdlib.h>
- #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;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。