linux驱动开发--内核链表

来源:互联网 发布:编程语言发展趋势 编辑:程序博客网 时间:2024/05/17 02:21

1、内核链表定义

在<Linux/list.h>中定义

[objc] view plain copy
  1. struct list_head{  
  2.   struct list_head *next, *prev;  
  3. };  
在list_head结构中包含两个指向list_head结构的指针next和prev,在实际使用中,它通常被组织成双向循环链表。

内核链表结构体不包含数据域,只包含维护链表的指针域。

内核链表被包含在其他数据结构体中使用。

初始化链表头INIT_LIST_HEAD函数
void INIT_LIST_HEAD(struct list_head *list);
list:待初始化链表头
插入节点list_add函数
void list_add(struct list_head *new, struct list_head *head);
void list_add_tail(struct list_head *new, struct list_head *head);

new:待插入到链表的新节点
head:待插入到链表的链表头

删除节点list_del函数
void list_del(struct list_head *entry);
entry:待删除的节点
提取数据结构list_entry宏
#define list_entry(ptr, type, member) container_of(ptr, type, member)
ptr:当前链表节点指针
type:包含该链表的数据结构体类型
member:在数据结构体类型中的list_head成员名称
返回:获取的数据结构体指针
实际是通过已知数据结构体中链表节点指针ptr,获取包含该链表节点的数据结构体指针

遍历链表list_for_each宏
#define list_for_each(pos, head) for(pos = (head)->next; prefetch(pos->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)

pos:list_head指针类型的循环变量
n:list_head指针类型的循环变量
head:待遍历链表的链表头

2、实例代码:

[objc] view plain copy
  1. /** 
  2. *Copyright (c) 2013.TianYuan 
  3. *All rights reserved. 
  4. * 
  5. *文件名称: listtest.c 
  6. *文件标识: 内核链表的使用 
  7. * 
  8. *当前版本:1.0 
  9. *作者:wuyq  
  10. * 
  11. *取代版本:xxx 
  12. *原作者:xxx 
  13. *完成日期:2013-11-18 
  14. */  
  15. #include <linux/init.h>  
  16. #include <linux/module.h>  
  17. #include <linux/err.h>  
  18. #include <linux/slab.h>  
  19. #include <linux/list.h>  
  20.   
  21. MODULE_LICENSE("GPL");  
  22.   
  23. #define EMPLOYEE_NUM    10  
  24.   
  25. struct employee  
  26. {  
  27.     char name[20];  
  28.     int id;  
  29.     int salary;  
  30.     int age;  
  31.     struct list_head list;  
  32. };  
  33.   
  34. /*定义链表头节点*/  
  35. struct list_head  employee_list;  
  36. struct employee *employeep = NULL;/*保存首地址*/  
  37. struct list_head *pos = NULL;/*list_for_each*/  
  38. struct employee *employee_tmp = NULL;  
  39. static int __init listtest_init(void)  
  40. {  
  41.     int i = 0;  
  42.       
  43.     /*初始化链表头节点*/  
  44.     INIT_LIST_HEAD(&employee_list);  
  45.       
  46.     /*申请employee空间*/  
  47.     employeep = kmalloc(sizeof(struct employee)*EMPLOYEE_NUM, GFP_KERNEL);  
  48.     if(IS_ERR(employeep)){  
  49.         printk("kmalloc failed!\n");  
  50.         return -ENOMEM;  
  51.     }  
  52.     memset(employeep, 0sizeof(struct employee)*EMPLOYEE_NUM);  
  53.     /*初始化每个struct*/  
  54.     for(i=0; i<EMPLOYEE_NUM; i++){  
  55.         sprintf(employeep[i].name"employee%d", i);  
  56.         /*true*/sprintf((employeep+i)->name, "employee%d", i);  
  57.         employeep[i].id = 10000 + i;  
  58.         employeep[i].salary = 10000 + 1000*i;  
  59.         /*添加节点到链表中*/  
  60.         list_add(&(employeep[i].list), &employee_list);  
  61.     }  
  62.     /*链表节点的遍历*/   
  63.     list_for_each(pos, &employee_list){  
  64.         employee_tmp = list_entry(pos, struct employee, list);  
  65.         printk("employee name :T=%s\tID:%d\tSalary:%d!\n",  
  66.                 employee_tmp->name,  
  67.                 employee_tmp->id,  
  68.                 employee_tmp->salary);  
  69.     }     
  70.           
  71.     return 0;  
  72. }  
  73.   
  74. static void __exit listtest_exit(void)  
  75. {  
  76.     int i = 0;  
  77.     for(i=0; i<EMPLOYEE_NUM; i++){  
  78.         list_del(&(employeep[i].list));  
  79.     }  
  80.       
  81.     kfree(employeep);  
  82. }  
  83.   
  84. module_init(listtest_init);  
  85. module_exit(listtest_exit);  

[plain] view plain copy
  1. KERNELDIR ?=/root/Desktop/work/ldd3/linux-2.6.31_TX2440A  
  2. PWD := $(shell pwd)  
  3. obj-m += listtest.o  
  4.   
  5. default:  
  6.     $(MAKE) -C $(KERNELDIR) M=$(PWD) modules  
  7.   
  8. clean:  
  9.     @rm -f *.o *.ord* *.sy* *.mod.* *.ko