linux驱动开发--内核链表
1、内核链表定义
在<Linux/list.h>中定义
- struct list_head{
- struct 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、实例代码:
- /**
- *Copyright (c) 2013.TianYuan
- *All rights reserved.
- *
- *文件名称: listtest.c
- *文件标识: 内核链表的使用
- *
- *当前版本:1.0
- *作者:wuyq
- *
- *取代版本:xxx
- *原作者:xxx
- *完成日期:2013-11-18
- */
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/err.h>
- #include <linux/slab.h>
- #include <linux/list.h>
- MODULE_LICENSE("GPL");
- #define EMPLOYEE_NUM 10
- struct employee
- {
- char name[20];
- int id;
- int salary;
- int age;
- struct list_head list;
- };
- /*定义链表头节点*/
- struct list_head employee_list;
- struct employee *employeep = NULL;/*保存首地址*/
- struct list_head *pos = NULL;/*list_for_each*/
- struct employee *employee_tmp = NULL;
- static int __init listtest_init(void)
- {
- int i = 0;
- /*初始化链表头节点*/
- INIT_LIST_HEAD(&employee_list);
- /*申请employee空间*/
- employeep = kmalloc(sizeof(struct employee)*EMPLOYEE_NUM, GFP_KERNEL);
- if(IS_ERR(employeep)){
- printk("kmalloc failed!\n");
- return -ENOMEM;
- }
- memset(employeep, 0, sizeof(struct employee)*EMPLOYEE_NUM);
- /*初始化每个struct*/
- for(i=0; i<EMPLOYEE_NUM; i++){
- sprintf(employeep[i].name, "employee%d", i);
- /*true*/sprintf((employeep+i)->name, "employee%d", i);
- employeep[i].id = 10000 + i;
- employeep[i].salary = 10000 + 1000*i;
- /*添加节点到链表中*/
- list_add(&(employeep[i].list), &employee_list);
- }
- /*链表节点的遍历*/
- list_for_each(pos, &employee_list){
- employee_tmp = list_entry(pos, struct employee, list);
- printk("employee name :T=%s\tID:%d\tSalary:%d!\n",
- employee_tmp->name,
- employee_tmp->id,
- employee_tmp->salary);
- }
- return 0;
- }
- static void __exit listtest_exit(void)
- {
- int i = 0;
- for(i=0; i<EMPLOYEE_NUM; i++){
- list_del(&(employeep[i].list));
- }
- kfree(employeep);
- }
- module_init(listtest_init);
- module_exit(listtest_exit);
- KERNELDIR ?=/root/Desktop/work/ldd3/linux-2.6.31_TX2440A
- PWD := $(shell pwd)
- obj-m += listtest.o
- default:
- $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
- clean:
- @rm -f *.o *.ord* *.sy* *.mod.* *.ko