上一章我们讲解了struct klist结构,并且知道这个结构怎么使用的问题,这一章中我们讲解struct klist结构在内核中的具体使用,也可能是在内核中唯一使用klist结构部分----类-设备迭代器(class_dev_inter),也就是我们在文章题目中所说的struct class_dev_inter
结构。
首先说明一下类迭代器的使用场景:
在内核中有一种设备模型为:类。每一个类设备模型下面有若干个device结构主要在class->p->class_devices结构的klist链表下面挂载。
如下图为class和class下挂载的类的数据模型图,其中class_private是struct class数据结构下一个成员:
class_dev_inter表征的意义:
class_dev_inter意为类-设备迭代器,其主要作用是迭代类下面挂载的所有的数据。至于具体迭代方法如下步骤:
1. 提取class->class_private下面的class_devices结构。
2. 把上述klist结构放入class_dev_inter下的i_klist指针下,并把要遍历的开始节点放入i_cur节点之下。
3. 从class_dev_inter->klist.i_cur遍历整个类下面的存活的节点。
上图表述提取出数据模型如下:
class_dev_inter结构:
主要有三部分组成:
类-设备迭代器头结点
类-设备迭代器开始结点
类-设备类型
具体的数据结构如下:
struct class_dev_iter {
struct klist_iter ki;
const struct device_type *type;
};
struct klist_iter {
struct klist *i_klist;
struct klist_node *i_cur;
};
class_dev_inter结构使用
类迭代器主要跟随着循环使用,首先要初始化类迭代器,然后遍历,最后才退出类迭代器。主要函数如下:
class_dev_inter_init
初始化迭代器本身参数比较复杂,需要跟随者一个迭代器指针,然后跟随者一个klist链表和开始位置,最后传入的是类设备类型。分别对应着class_dev_inter结构体的各个部分。
class_dev_inter_next
只需要传入class_dev_inter结构体返回的是struct device结构,如果迭代完全则返回NULL
class_dev_inter_exit
退出类迭代器,只需要传入class_dev_inter指针即可
以上三个函数的圆形如下:
/**可见其传入参数为inter, class, start, type*/
void class_dev_iter_init(struct class_dev_iter *iter, struct class *class,
struct device *start, const struct device_type *type)
{
struct klist_node *start_knode = NULL;
if (start)
start_knode = &start->knode_class;
klist_iter_init_node(&class->p->class_devices, &iter->ki, start_knode);
iter->type = type;
}
EXPORT_SYMBOL_GPL(class_dev_iter_init);
/**
* class_dev_iter_next - iterate to the next device
* @iter: class iterator to proceed
*
* Proceed @iter to the next device and return it. Returns NULL if
* iteration is complete.
*
* The returned device is referenced and won't be released till
* iterator is proceed to the next device or exited. The caller is
* free to do whatever it wants to do with the device including
* calling back into class code.
*/
/**只需要传入迭代器本身即可**/
struct device *class_dev_iter_next(struct class_dev_iter *iter)
{
struct klist_node *knode;
struct device *dev;
while (1) {
knode = klist_next(&iter->ki);
if (!knode)
return NULL;
dev = container_of(knode, struct device, knode_class);
if (!iter->type || iter->type == dev->type)
return dev;
}
}
EXPORT_SYMBOL_GPL(class_dev_iter_next);
/**
* class_dev_iter_exit - finish iteration
* @iter: class iterator to finish
*
* Finish an iteration. Always call this function after iteration is
* complete whether the iteration ran till the end or not.
*/
/**删除迭代器也只需要传入迭代器本身即可**/
void class_dev_iter_exit(struct class_dev_iter *iter)
{
klist_iter_exit(&iter->ki);
}