下面我们学习一下linux内核中list模块的使用.doc
文本预览下载声明
下面我们学习一下linux内核中list模块的使用
List模块是linux内核提供的循环链表函数集。头文件是:linux/list.h
主要数据结构:
struct list_head {
struct list_head *next, *prev;
};
可见这是一个双向链表。
使用之前必须初始化一个链表头,可以使用下面的宏直接定义并且初始化一个链表头:
LIST_HEAD(name)
宏参数name是链表头定义名。
例如:
LIST_HEAD(listHead)
使用时,你的数据结构中必须包含struct list_head类成员,例如:
Struct myNode{
Int a;
Struct list_head listNode;
};
Struct myNode nodeVar;
调用list_add函数可以将一个数据节点加入到链表中:
List_add_tail(nodeVar-listNode, listHead);
其实它是把nodeVar中的listNode元素接入链表末尾
List_add(nodeVar-listNode, listHead)
将元素加入到链表首位置,即链表头listHead的下一个位置。
,整个链表的结构如下:
假如有n个struct myNode变量加入了这个链表,那么怎样查找元素a =100的节点呢?
使用list_for_each_entry
代码如下:
#define list_for_each_entry(pos, head, member) for (pos = list_entry((head)-next, typeof(*pos), member); pos-member != (head); pos = list_entry(pos-member.next, typeof(*pos), member))
#define list_entry(ptr, type, member) container_of(ptr, type, member)
其中pos是暂存的结构体指针,member是结构体内部的struct listhead结构变量。
Head是链表头。
一般使用的时候:
list_for_each_entry(pos, head, member)
{
…..
}
例如:
Struct myNode* Pos
list_for_each_entry(Pos, listHead, listNode)
{
If(Pos-a == 100)
{
…….
}
}
如果涉及到Pos的指针内存操作,例如释放等,可以使用函数:
#define list_for_each_entry_safe(pos, n, head, member) for (pos = list_entry((head)-next, typeof(*pos), member), n = list_entry(pos-member.next, typeof(*pos), member); pos-member != (head); pos = n, n = list_entry(n-member.next, typeof(*n), member))
这个函数使用n来保存pos的值,以免pos释放后继续操作pos造成内存错误。
例子:
Struct myNode* cPos, nPos;
list_for_each_entry_safe(cPos, nPos, listHead, listNode)
{
list_del(cPos);
free(cPos);
}
注:
container_of(ptr, type, member)是那就是根据一个结构体变量中的一个域成员变量的指针来获取指向整个结构体变量的指针。
例如container_of(nodeVar-listNode, struct myNode, listNode)
得到的将是nodeVar的地址。
它的功能相当与下面的代码:
Ptr - ((type*)0-member)
参见下面的文章:
问题:如何通过结构中的某个变量获取结构本身的指针???关于container_of见kernel.h中:/*** container_of - cast a member of a structure out to the containing structure* @ptr:???? the pointer to the member.* @type:???? th
显示全部