linux设备驱动程序(第三版)阅读笔记(十一)
来源:互联网 发布:如何加盟菜鸟网络 编辑:程序博客网 时间:2024/05/21 22:47
说明:版权所有归作者,只供学习交流,若有其它用途请联系作者,转载请遵守IT人职业规范,请注明转载地址
第十一章:内核的数据类型
1,(内核使用的数据类型)内核使用的数据类型主要被分成三大类:类似int这样的标准C语言类型,类似u32这样的有确定大小的类型,以及像pid_t这样的用于特定内核对象的类型。
2,(内核链表)就像很多其他程序一样,操作系统内核经常需要维护数据结构的列表。有时,linux内核中同时存在多个链表的实现代码。为了减小重复代码的数量,内核开发者已经建立了一套标准的循环、双向链表的实现。如果你需要操作链表,那么建议你使用这一内核设施。
当使用这些链表接口时,应该始终牢记这些链表函数不进行任何锁定。如果你的驱动程序有可能试图对同一个链表执行并发操作的话,则有责任实现一个锁方案。否则,崩溃的链表结构体、数据丢失、内核混乱等问题是很难诊断的。
为了能使用这个链表机制,驱动程序必须包含头文件<linux/list.h>。该文件定义了一个简单的list_head类型的结构体。
struct list_head
{
struct list_head *next,*prev;
}
用于实际代码的链表几乎总是由某种结构类型构成,每个结构描述链表中的一项。为了在代码中使用Linux链表设施,只需要在构成链表的结构里面嵌入一个list_head。
链表头通常是一个独立的list_head结构。
在使用链表之前,必须用INIT_LIST_HEAD宏来初始化链表头。可如下声明并初始化一个实际的链表头:
struct list_head todo_list;
INIT_LIST_HEAD(&todo_list);
也可在编译时像下面这样初始化链表:
LIST_HEAD(todo_list);
链表的操作:
list_add(struct list_head *new, struct list_head *head);
在链表头添加新项----通常在链表的头部。这样,它可以被用来建立栈。但需要注意的是,head并不一定非得是链表名义上的头;如果传递了一个恰巧位于链表中间某处的list_head结构体,新项会紧跟在它后面。因为linux链表是循环式的,链表头通常与其他的项没有本质上的区别。
list_add_tail(struct list_head *new, struct list_head *head);
在给定链表的末尾处添加一个新的项。因此,可用list_add_tail来创建先进先出(FIFO)队列。
list_del(struct list_head *entry);
list_del_init(struct list_head *entry);
删除链表中的给定项。如果该项还可能被重新插入到另一个链表中的话,应该使用list_del_init,它会重新初始化链表的指针。
list_move(struct list_head *entry, struct list_head *head);
list_move_tail(structlist_head *entry, struct list_head *head);
把给定项移动到链表的开始处。如果要把给定项放到新链表的末尾,使用list_move_tail。
list_empty(struct list_head *head);
清空链表,如果给定的链表为空,返回一个非零值。
list_splice(struct list_head *list, struct list_head *head);
通过在head之后插入list来合并两个链表。
list_head结构体有利于实现具有类似结构的链表,但调用程序通常对组成链表的大结构感兴趣。因此,可利用list_entry宏将一个list_head结构指针映射回指向包含它的大结构的指针。换句话说list_entry的作用就是以知数据结构中的节点指针ptr,提取大数据结构中的其他信息。可如下调用宏:
list_entry(struct list_head *ptr, type_of_struct, field_name);
其中,ptr是指向正被使用的struct list_head的指针,type_of_struct是包含ptr的结构类型,field_name是结构中链表字段的名字。
list_for_each(struct list_head *cursor, struct list_head *list);
该宏创建一个for循环,每当游标指向链表中的下一项时执行一次。在遍历链表时要注意对它的修改。
List_for_each_prev(struct list_head *cursor, struct list_head * list);
该版本向后遍历链表。
List_for_each_safe(struct list_head *cursor, struct list_head *next, struct list_head *list);
如果循环可能会删除链表中的项,就应该使用该版本。它只是简单地在循环的开始处把链表中的下一项存储在next中,这样如果cursor所指的项被删除也不会造成混乱。
List_for_each_entry(type*cursor, struct list_head *list, member);
List_for_each_entry_safe(type*cursor, type *next, struct list_head *list,member);
这些宏使处理一个包含给定类型的结构体的链表时更加容易。这里,cursor是指向包含结构体类型的指针,member是包含结构体内list_head结构体的名字。使用这些宏就不需要在循环内调用list_entry了。
- linux设备驱动程序(第三版)阅读笔记(十一)
- linux设备驱动程序(第三版)阅读笔记(一)
- linux设备驱动程序(第三版)阅读笔记(二)
- linux设备驱动程序(第三版)阅读笔记(三)
- linux设备驱动程序(第三版)阅读笔记(四)
- linux设备驱动程序(第三版)阅读笔记(五)
- linux设备驱动程序(第三版)阅读笔记(六)
- linux设备驱动程序(第三版)阅读笔记(七)
- linux设备驱动程序(第三版)阅读笔记(八)
- linux设备驱动程序(第三版)阅读笔记(九)
- linux设备驱动程序(第三版)阅读笔记(十)
- 《Linux设备设备驱动程序(第三版)》学习笔记之一:scull设备的使用
- 《Linux设备设备驱动程序(第三版)》学习笔记之三:sleepy设备的使用
- 《Linux设备设备驱动程序(第三版)》学习笔记之三:sleepy设备的使用
- Linux设备驱动程序(第三版)学习
- 【Linux设备驱动程序(第三版)】----HelloWorld
- 【Linux设备驱动程序(第三版)】----Scull
- 【Linux设备驱动程序(第三版)】----ioctl
- FAT文件系统原理
- linux设备驱动程序(第三版)阅读笔记(十)
- 排序算法系列之希尔排序
- Css3+Js 漂亮时钟
- 解决Incorrect integer value: '' for column 'id' at row 1的方法
- linux设备驱动程序(第三版)阅读笔记(十一)
- 如何MyEclipse中显示WEB-INF文件夹下的classes目录以及目录中的class文件
- 引用与指针的区别
- strstr的应用---Hd 2054 A == B ?
- 对文件列表List<File>按名称排序
- NTFS vs FAT vs exFAT
- 在linux(ubuntu11.10)下goagent实现开机自动加载运行
- 学习笔记_uml_状态图
- 程序人生--2009年(53)