小结:
下面这个图应该能说明全部问题
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
函数列表:
void klist_init
初始化klist,主要操作是挂空k->k_list,初始化k_lock锁,挂上get和put函数
void klist_add_head(struct klist_node * n, struct klist * k)
void klist_add_tail(struct klist_node * n, struct klist * k)
初始化node链表并将其挂到klist链表的表首
void klist_del(struct klist_node * n)
从klist中删除指定的node节点,如果该节点不是klist中最后一个节点,则执行init时指定的put函数
void klist_remove(struct klist_node * n)
这个函数实际是调用了klist_del函数,只是多了一步wait_for_completion,而该信号的completion操作则是在klist_release函数中发出,klist_release的调用在klist_del中执行
//容器模块
void klist_iter_init_node
void klist_iter_init(struct klist * k, struct klist_iter * i)
容器的初始化,具体操作是关联上klist,klist->head(node链表),将node设置为当前节点。
klist_iter_init的操作只是调用klist_iter_init_node(k, I, NULL)
void klist_iter_exit(struct klist_iter * i)
容器的当前node节点存在,则从klist中删除当前node节点(klist_del),并将当前节点挂空
从这个函数的操作,我们可以推测一下,容器实际是对klist中指定的一个节点进行操作
struct klist_node * klist_next(struct klist_iter * i)
从klist的node链表中找到下一个节点,挂到容器i->cur上,并执行之前i->cur指向的节点的klist->put函数,最后返回刚找到的下一个节点。
klist模型大概如下:
klist->node挂载着很多node链表,而每一个node链表下又挂载着很多node子链表,klist_next有一个分支操作就是当一个node链表的所有子node都找完后,就会从klist->node链表的下一个链表开始找新的node
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
结构体说明:
struct klist {
spinlock_t k_lock;
struct list_head k_list; //挂载klist_node结构体
void (*get)(struct klist_node *);
void (*put)(struct klist_node *);
};
struct klist_node {
struct klist * n_klist;
struct list_head n_node;
struct kref n_ref; //引用计数
struct completion n_removed;
};
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//klist的初始化操作
void klist_init(
struct klist * k,
void (*get)(struct klist_node *),
void (*put)(struct klist_node *))
{
INIT_LIST_HEAD(&k->k_list); //链表挂空
spin_lock_init(&k->k_lock); //自旋锁
k->get = get;
k->put = put; //关联引用和释放计数函数
}
EXPORT_SYMBOL_GPL(klist_init);
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//将n->node挂到k->k_list的表首
static void add_head(struct klist * k, struct klist_node * n)
{
list_add(&n->n_node, &k->k_list);
//__list_add(&n->n_node, &k->k_list, &k->k_list ->next);
}
//将n->node挂到k->list的表尾
static void add_tail(struct klist * k, struct klist_node * n)
{
list_add_tail(&n->n_node, &k->k_list);
}
//node的初始化,也就是n->node,即k->list的成员
static void klist_node_init(struct klist * k, struct klist_node * n)
{
INIT_LIST_HEAD(&n->n_node); //node链表挂空
init_completion(&n->n_removed); //初始化等待队列
kref_init(&n->n_ref); //初始化计数
n->n_klist = k; //关联上klist,也可以理解为父设备
if (k->get) //父设备的引用加1
k->get(n);
}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//将node链表初始化并挂到list链表的表首
void klist_add_head(struct klist_node * n, struct klist * k)
{
klist_node_init(k, n); //初始化node节点
add_head(k, n); //node加入klist中
}
//将node链表初始化并挂到list链表的表尾
void klist_add_tail(struct klist_node * n, struct klist * k)
{
klist_node_init(k, n);
add_tail(k, n);
}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//释放kref成员所在结构体在klist上的链接
static void klist_release(struct kref * kref)
{
//通过kref获取该成员的结构体宿主
struct klist_node * n = container_of(kref, struct klist_node, n_ref);
list_del(&n->n_node); //将node链表从他所在的链表中断开
complete(&n->n_removed); //释放等待队列
n->n_klist = NULL; //将node结构体的父设备挂空
}
//将n->n_ref计数减1,并调用klist_release函数
static int klist_dec_and_del(struct klist_node * n)
{
return kref_put(&n->n_ref, klist_release);
}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//从klist中删除指定的node节点,并调用初始化时指定的put函数
//如果是最后一个节点则不再调用put函数
void klist_del(struct klist_node * n)
{
struct klist * k = n->n_klist; //获取node的父klist设备
void (*put)(struct klist_node *) = k->put; //获取klist的put函数
spin_lock(&k->k_lock);
if (!klist_dec_and_del(n)) put = NULL; //从klist中删除本node节点,如果这是klist的最后一个节点,则put函数挂空
spin_unlock(&k->k_lock);
if (put)
put(n); //执行put函数,参数为已经删除的节点
}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//移除node节点
void klist_remove(struct klist_node * n)
{
klist_del(n); //这个函数的实现就在上面
wait_for_completion(&n->n_removed);
//等待completion信号,该信号在klist_release函数中发出
}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//探测指定node的父设备是否指定,没指定就返回1,指定就返回0
int klist_node_attached(struct klist_node * n)
{
return (n->n_klist != NULL);
}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//初始化容器
void klist_iter_init_node(
struct klist * k, //klist链表
struct klist_iter * i, //容器
struct klist_node * n) //node链表
{
i->i_klist = k;
i->i_head = &k->k_list; //klist的node链表
i->i_cur = n;
if (n)
kref_get(&n->n_ref); //node节点存在,则节点的引用计数加1
}
//容器的初始化,node为NULL
void klist_iter_init(struct klist * k, struct klist_iter * i)
{
klist_iter_init_node(k, i, NULL);
}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//容器的退出
void klist_iter_exit(struct klist_iter * i)
{
//容器的当前node节点存在,则从klist中删除当前node节点,并将当前节点挂空
if (i->i_cur) {
klist_del(i->i_cur);
i->i_cur = NULL;
}
}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//根据成员返回klist_node宿主
static struct klist_node * to_klist_node(struct list_head * n)
{
return container_of(n, struct klist_node, n_node);
}
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
struct klist_node * klist_next(struct klist_iter * i)
{
struct list_head * next;
struct klist_node * lnode = i->i_cur; //当前操作的节点
struct klist_node * knode = NULL;
void (*put)(struct klist_node *) = i->i_klist->put; //父klist链表中的put函数
spin_lock(&i->i_klist->k_lock);
//当前操作节点存在
if (lnode) {
next = lnode->n_node.next; //获取当前节点的下一个节点
if (!klist_dec_and_del(lnode)) //删除当前节点
put = NULL;
}
//当前操作节点不存在,下一个接是klist->node链表的下一个node链表
else
next = i->i_head->next;
//下一个节点不是klist->node的链表头
if (next != i->i_head) {
knode = to_klist_node(next); //取出节点
kref_get(&knode->n_ref); //引用计数
}
i->i_cur = knode; //容器的当前节点修改为找到的下一个节点
spin_unlock(&i->i_klist->k_lock);
if (put && lnode)
put(lnode); //执行之前节点的put函数
//返回找到的下一个节点
return knode;
}