Chinaunix首页 | 论坛 | 博客
  • 博客访问: 493849
  • 博文数量: 223
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2145
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-01 10:23
个人简介

该坚持的时候坚持,该妥协的时候妥协,该放弃的时候放弃

文章分类

全部博文(223)

文章存档

2017年(56)

2016年(118)

2015年(3)

2014年(46)

我的朋友

分类: 嵌入式

2016-10-31 22:17:11

一、内核链表简介
链表是一种常用的数据结构,它通过指针一系列数据节点连接成一条数据链。相对于数组,链表具有更好的动态性,建立链表时无需预先知道数据总量,可以随机分配空间,可以高效地在链表中的任意位置实时插入或删除数据。链表的开销主要是访问的顺序性和组织链的空间损失。

二、内核链表结构
  1. struct list_head
  2. {
  3.     struct list_head *next, *prev;
  4. };
list_head结构包含两个指向list_head结构的指针
prev和next,由此可见,内核的链表具备双链表功能,实际上,通常它都组织成双向循环链表

三、内核链表-函数
1.INIT_LIST_HEAD:创建链表
原型:void INIT_LIST_HEAD(struct list_head *list)
*list:要初始化的list指针地址。
  1. #define LIST_HEAD_INIT(name) { &(name), &(name) }

  2. #define LIST_HEAD(name) \
  3.     struct list_head name = LIST_HEAD_INIT(name)

  4. static inline void INIT_LIST_HEAD(struct list_head *list)
  5. {
  6.     list->next = list;                                //将list->next指向list
  7.     list->prev = list;                                //将list->prev指向list
  8. }
2. list_add:在链表头插入节点
原型:void list_add(struct list_head *new, struct list_head *head);
*new:新增加的链表结构
*head:需要新增的链表位置(后)
  1. /*
  2.  * Insert a new entry between two known consecutive entries.
  3.  *
  4.  * This is only for internal list manipulation where we know
  5.  * the prev/next entries
  6.  */
  7. #ifndef CONFIG_DEBUG_LIST
  8. static inline void __list_add(struct list_head *new,
  9.              struct list_head *prev,
  10.              struct list_head *next)
  11. {
  12.     next->prev = new;                        //head的后面链表的prev指针指向new
  13.     new->next = next;                        //new的next指向head的next结构地址
  14.     new->prev = prev;                        //new的prev指向head的结构地址
  15.     prev->next = new;                        //head的next指向new的结构地址
  16. }
  17. #else
  18. extern void __list_add(struct list_head *new,
  19.              struct list_head *prev,
  20.              struct list_head *next);
  21. #endif

  22. /**
  23.  * list_add - add a new entry
  24.  * @new: new entry to be added
  25.  * @head: list head to add it after
  26.  *
  27.  * Insert a new entry after the specified head.
  28.  * This is good for implementing stacks.
  29.  */
  30. static inline void list_add(struct list_head *new, struct list_head *head)
  31. {
  32.     __list_add(new, head, head->next);
  33. }

3. list_add_tail:在链表尾插入节点
原型:list_add_tail(struct list_head *new, struct list_head *head);
*new:新增的结构位置
*head:开始的位置
  1. /**
  2.  * list_add_tail - add a new entry
  3.  * @new: new entry to be added
  4.  * @head: list head to add it before
  5.  *
  6.  * Insert a new entry before the specified head.
  7.  * This is useful for implementing queues.
  8.  */
  9. static inline void list_add_tail(struct list_head *new, struct list_head *head)
  10. {
  11.     __list_add(new, head->prev, head);                         //这里head->prev指向的就是最后的一个lis_head结构
  12. }

4. list_del:删除节点
原型:void list_del(struct list_head *entry);
*entry需要删除的结构位置
  1. /*
  2.  * Delete a list entry by making the prev/next entries
  3.  * point to each other.
  4.  *
  5.  * This is only for internal list manipulation where we know
  6.  * the prev/next entries
  7.  */
  8. static inline void __list_del(struct list_head * prev, struct list_head * next)
  9. {
  10.     next->prev = prev;                //把后面的指向前面的
  11.     prev->next = next;                //把前面的指向了后面的
  12. }

  13. /**
  14.  * list_del - deletes entry from list.
  15.  * @entry: the element to delete from the list.
  16.  * Note: list_empty() on entry does not return true after this, the entry is
  17.  * in an undefined state.
  18.  */
  19. #ifndef CONFIG_DEBUG_LIST
  20. static inline void __list_del_entry(struct list_head *entry)
  21. {
  22.     __list_del(entry->prev, entry->next);
  23. }

  24. static inline void list_del(struct list_head *entry)
  25. {
  26.     __list_del(entry->prev, entry->next);
  27.     entry->next = LIST_POISON1;
  28.     entry->prev = LIST_POISON2;
  29. }
  30. #else
  31. extern void __list_del_entry(struct list_head *entry);
  32. extern void list_del(struct list_head *entry);
  33. #endif

5. list_entry:取出节点
原型:list_entry(ptr, type, member);
ptr:链表中某个成员的list_head的位置
type:链表中内嵌的结构,用户自己的
member:用户结构中的list_head的成员名字
  1. /**
  2.  * container_of - cast a member of a structure out to the containing structure
  3.  * @ptr:    the pointer to the member.
  4.  * @type:    the type of the container struct this is embedded in.
  5.  * @member:    the name of the member within the struct.
  6.  
  7.  */
  8. #define container_of(ptr, type, member) ({            \
  9.     const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
  10.     (type *)( (char *)__mptr - offsetof(type,member) );})


  11. /**
  12.  * list_entry - get the struct for this entry
  13.  * @ptr:    the &struct list_head pointer.
  14.  * @type:    the type of the struct this is embedded in.
  15.  * @member:    the name of the list_struct within the struct.
  16.  */
  17. #define list_entry(ptr, type, member) \
  18.     container_of(ptr, type, member)

6. list_for_each:遍历链表
原型:list_for_each(pos,head)
pos:搜索的到位置
head:起始位置
  1. /**
  2.  * list_for_each    -    iterate over a list
  3.  * @pos:    the &struct list_head to use as a loop cursor.
  4.  * @head:    the head for your list.
  5.  */
  6. #define list_for_each(pos, head) \
  7.     for (pos = (head)->next; prefetch(pos->next), pos != (head); \
  8.             pos = pos->next)

四、代码编写学习
mylist.c
  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/list.h>

  4. struct score
  5. {
  6.     int num;
  7.     int english;
  8.     int math;
  9.     struct list_head list;
  10. };

  11. struct list_head score_head;
  12. struct list_head *pos;
  13. struct score stu1,stu2,stu3;
  14. struct score *tmp;

  15. static int mylist_init()
  16. {
  17.     /*初始化链表*/
  18.     INIT_LIST_HEAD(&score_head);

  19.     stu1.num = 1;
  20.     stu1.english = 90;
  21.     stu1.math = 89;
  22.     /*将链表连入score_head尾部*/
  23.     list_add_tail(&(stu1.list), &score_head);

  24.     stu2.num = 2;
  25.     stu2.english = 92;
  26.     stu2.math = 91;
  27.     list_add_tail(&(stu2.list), &score_head);

  28.     stu3.num = 3;
  29.     stu3.english = 94;
  30.     stu3.math = 95;
  31.     list_add_tail(&(stu3.list), &score_head);
  32.     /*遍历链表*/
  33.     list_for_each(pos, &score_head)
  34.     {
  35.         /*找到链表对应的结构体节点*/
  36.         tmp = list_entry(pos, struct score, list);
  37.     printk("No %d, english is %d, math is %d\n",tmp->num,tmp->english,tmp->math);
  38.     }

  39.     return 0;
  40. }

  41. static void mylist_exit()
  42. {
  43.     list_del(&(stu1.list));
  44.     list_del(&(stu2.list));
  45. }

  46. module_init(mylist_init);
  47. module_exit(mylist_exit);

阅读(440) | 评论(0) | 转发(0) |
0

上一篇:Linux内核子系统

下一篇:Linux驱动开发前奏

给主人留下些什么吧!~~