\lib\klist.c

来源:互联网 发布:ps手绘软件 编辑:程序博客网 时间:2024/06/07 06:05
 

小结:

 

下面这个图应该能说明全部问题

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

函数列表:

 

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;

}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 身份证指纹错了怎么办 指纹手机丢了怎么办 异地办理临时身份证怎么办 杭州办理外地身份证怎么办 办理身份证没有户口本怎么办 2018身份证掉了怎么办 双户口注销社保怎么办 常用户口被注销怎么办 刚到厦门怎么办身份证 新疆身份证丢了怎么办 技能证书丢了怎么办 16岁拍身份证怎么办 16岁以下怎么办身份证 办身份证要证明怎么办 15岁怎么办银行卡淘宝 满16岁怎么办银行卡 电脑最小化后不见了怎么办 满16周岁怎么办银行卡 给儿童办身份证怎么办 当兵前身份证号码不符怎么办 身份证后六位密码x怎么办 借了贷款人死了怎么办 贷款实在还不起怎么办 个人贷款还不起怎么办 珠海派出所办事不公平怎么办 改身份证后学籍怎么办? 威海身份证丢了怎么办 车牌轻微变形了怎么办 车牌照丢一个怎么办 小车车牌掉了怎么办 车牌撞变形了怎么办 车牌烂了一块怎么办 机动车牌照丢了怎么办 汽车想换车牌怎么办 机动车前牌照丢失怎么办 汽车后牌照丢失怎么办 机动车扣分超证怎么办 联通香港无服务怎么办 长乐改区 闽侯怎么办 学校代码查不到怎么办 买票没带身份证怎么办