linux驱动开发--内核链表
1、内核链表定义
在<linux/list.h>中定义
struct list_head{ struct list_head *next, *prev; };在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、实例代码:
/** *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
最后更新:2017-04-03 12:53:59
上一篇:
linux驱动开发--字符设备:自动创建设备节点
下一篇:
Java to download a file from internet
VPC最佳实践(二):VPC内如何使用云产品
跟着实例学习ZooKeeper的用法: 队列
站在5G大门口,重新认识高通的三组基因
前端在人工智能时代能做些什么?
????????????????????????? ???????????????????????????????????????-??????-????????????-?????????
Sql Server 常用函数
云计算市场群雄并起,“架构云”突破重围成为新宠
Android串口通信(基于Tiny6410平台)
游戏安全资讯精选 2017 年第一期:流量攻击态势严峻,微软7月漏洞汇总和修复建议
深入理解Java内存模型(四)——volatile