Linux内核驱动学习(六)----内核链表
2015-03-06 22:23
288 查看
回顾链表的概念
Linux内核链表:双向循环链表。
内核链表的设计思想:实现尽可能的代码重用可以使大量的链表设计为单个链表。
list_head 结构包含两个指向list_head结构的指针 prev 和 next,由此可见内核的链表具有双链表的功能,实际上,通常它都组织成双向循环链表,这样其能达到的效率最高。
注:
1>以上链表不含数据域,可以嵌入到任何结构中--->这样可以不考虑包含list_head指针的对象结构,进而不需要重写链表的基本操作函数
2>一个结构体中可以含有多个list域--->这样就可以将一个链表挂载到多个不同链表中,例:Linux内核会将进程数据结构(task_struct)同时挂载到任务链表、优先级链表上去。范例:
2、list_add: 在链表头插入节点。
3、list_add_tail : 链表尾插入节点
4、list_del:删除节点
5、list_entry:取出节点
6、list_for_each: 遍历链表
在/linux/list.h查找以下函数,分析其如何实现?
1、INIT_LIST_HEAD:创建/初始化链表---在Linux内核中查找其原型
使list_head链表的前驱和后继都指向其自身。进而初始化
2、list_add: 在链表头插入节点。
追踪 __list_add(new, head, head->next);
3、list_add_tail : 链表尾插入节点
4、list_del:删除节点
list_del()函数将删除后的prev\next指针分别设为LIST_POISON1、LIST_POISON2
两个特殊值,是为了保证不在链表中的节点项不可访问,对以上两值的访问将引起页面故障
5、list_entry:取出节点,返回指向包含指针域的外部结构的指针
6、liast_for_each: 遍历链表---利用source insight 查找其相关用法
可以看做是一个for循环,游标从由head指向的表头节点开始,直到pos到达节点指针head结束。
参考用法。
主要方法为参考Linux内核代码,学习对应函数的用法,以实现整个链表。
部分参考博客:http://blog.csdn.net/houxn22/article/details/30223441
部分参考博客:http://blog.csdn.net/tigerjibo/article/details/8299599#t22
Linux内核链表:双向循环链表。
内核链表的设计思想:实现尽可能的代码重用可以使大量的链表设计为单个链表。
内核链表的结构
(代码位于include/linux/list.h中):struct list_head { struct list_head *next,*prev; }
list_head 结构包含两个指向list_head结构的指针 prev 和 next,由此可见内核的链表具有双链表的功能,实际上,通常它都组织成双向循环链表,这样其能达到的效率最高。
注:
1>以上链表不含数据域,可以嵌入到任何结构中--->这样可以不考虑包含list_head指针的对象结构,进而不需要重写链表的基本操作函数
2>一个结构体中可以含有多个list域--->这样就可以将一个链表挂载到多个不同链表中,例:Linux内核会将进程数据结构(task_struct)同时挂载到任务链表、优先级链表上去。范例:
struct score_list { char name; struct list_head *next,*prev; };
如何构造内核链表?
在特定对象的的结构中定义一个list_head(只含指针域的结构),通过这个成员将特定的对象连接起来,形成列表,然后通过通用链表函数对其进行插入、删除等操作。。操作内核链表的函数:
1、INIT_LIST_HEAD:创建/初始化链表---在Linux内核中查找其原型2、list_add: 在链表头插入节点。
3、list_add_tail : 链表尾插入节点
4、list_del:删除节点
5、list_entry:取出节点
6、list_for_each: 遍历链表
在/linux/list.h查找以下函数,分析其如何实现?
1、INIT_LIST_HEAD:创建/初始化链表---在Linux内核中查找其原型
static inline void INIT_LIST_HEAD(struct list_head *list) { list->next = list; list->prev = list; }
使list_head链表的前驱和后继都指向其自身。进而初始化
2、list_add: 在链表头插入节点。
/** * list_add - add a new entry //增加新节点 * @new: new entry to be added //参数new:将要被增加的节点入口 * @head: list head to add it after //参数head:增加节点在链表list_head的的表头的后面。 * Insert a new entry after the specified head. * This is good for implementing stacks.---》可用于实现栈 */ static inline void list_add(struct list_head *new, struct list_head *head) { __list_add(new, head, head->next);// 在head与head->next之间插入新节点 }
追踪 __list_add(new, head, head->next);
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; }
3、list_add_tail : 链表尾插入节点
/** * list_add_tail - add a new entry //增加新节点 * @new: new entry to be added //新增加的节点 * @head: list head to add it before //增加节点在head之前 * * Insert a new entry before the specified head. * This is useful for implementing queues. //可用于实现队列 */ static inline void list_add_tail(struct list_head *new, struct list_head *head) { __list_add(new, head->prev, head); //在head之前与head->prev之间插入节点,即在链表队尾插入 }
4、list_del:删除节点
static inline void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); entry->next = LIST_POISON1; entry->prev = LIST_POISON2; }
list_del()函数将删除后的prev\next指针分别设为LIST_POISON1、LIST_POISON2
两个特殊值,是为了保证不在链表中的节点项不可访问,对以上两值的访问将引起页面故障
5、list_entry:取出节点,返回指向包含指针域的外部结构的指针
/** * list_entry - get the struct for this entry --->返回指向节点的结构的指针(包含head_list的外部结构) * @ptr: the &struct list_head pointer. --->pos * @type: the type of the struct this is embedded in. --->嵌入对象的结构类型 * @member: the name of the list_struct within the struct. --->嵌入对象的结构中的指针域list_head结构的名字 */ #define list_entry(ptr, type, member) \ container_of(ptr, type, member)
6、liast_for_each: 遍历链表---利用source insight 查找其相关用法
<pre name="code" class="html">/** * list_for_each - iterate over a list * @pos: the &struct list_head to use as a loop cursor. //遍历过程中的游标,指向各个节点 * @head: the head for your list. //指向表头的head */ #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next)
可以看做是一个for循环,游标从由head指向的表头节点开始,直到pos到达节点指针head结束。
参考用法。
主要方法为参考Linux内核代码,学习对应函数的用法,以实现整个链表。
部分参考博客:http://blog.csdn.net/houxn22/article/details/30223441
部分参考博客:http://blog.csdn.net/tigerjibo/article/details/8299599#t22
相关文章推荐
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】全面解析Linux内核的同步与互斥机制--同步篇
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】全面解析Linux内核的同步与互斥机制--互斥篇
- linux驱动学习--第四天:第三章 linux内核以及内核编程 之 在Linux内核中新增程序的方法
- 内核驱动开发第四天linux内核链表
- linux内核学习(17)内核编程基本功之内核链表list_entry
- linux内核学习(17)内核编程基本功之内核链表list_entry
- Linux内核与驱动开发学习总结:内核访问外设IO.map_desc和ioremap(七)
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】详解Linux内核之双向循环链表
- Linux内核驱动学习(三)----内核模块基础 | 设计 | 可选项
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】Oops在Linux 2.6内核+PowerPC架构下的前世今生
- uclinux内核中的I2C驱动学习
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】揭开Linux Proc文件系统的神秘面纱
- 面对不断升级的内核,如何学习linux设备驱动
- Windows内核学习笔记(一)--浅谈驱动对象、设备对象与请求
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】深入剖析Linux中断机制之三--Linux对异常和中断的处理
- uclinux内核中的I2C驱动学习
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】Linux系统调用的实现机制分析
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】Linux内核抢占实现机制分析
- 安装内核源代码(驱动学习)
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】深入剖析Linux中断机制之目录