注释仅代表个人理解,难免有错误之处,仅供参考!

  1 /*

  2  *  linux/drivers/base/map.c

  3  *

  4  * (C) Copyright Al Viro 2002,2003

  5  *    Released under GPL v2.

  6  *

  7  * NOTE: data structure needs to be changed.  It works, but for large dev_t

  8  * it will be too slow.  It is isolated, though, so these changes will be

  9  * local to that file.

 10  */

 11 

 12 #include <linux/module.h>

 13 #include <linux/slab.h>

 14 #include <linux/mutex.h>

 15 #include <linux/kdev_t.h>

 16 #include <linux/kobject.h>

 17 #include <linux/kobj_map.h>

 18 

 19 struct kobj_map {

 20     struct probe {

 21         struct probe *next;

 22         dev_t dev;

 23         unsigned long range;

 24         struct module *owner;

 25         kobj_probe_t *get;

 26         int (*lock)(dev_t, void *);

 27         void *data;

 28     } *probes[];

 29     struct mutex *lock;

 30 };

 31 

 32 int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,

 33          struct module *module, kobj_probe_t *probe,

 34          int (*lock)(dev_t, void *), void *data)

 35 {

 36     /* [cgw]: 计算MAJOR(dev)到MAJOR(dev + range - 1)有几个

 37           * 主设备,由于主设备号都一样,所以这里n = 1

 38           */

 39     unsigned n = MAJOR(dev + range - ) - MAJOR(dev) + ;

 40     /* [cgw]: 以主设备号为索引 */

 41     unsigned index = MAJOR(dev);

 42     unsigned i;

 43     struct probe *p;

 44 

 45     /* [cgw]: 主设备超出255个 */

 46     if (n > )

 47         n = ;

 48     /* [cgw]: 分配n个struct probe内存空间*/

 49     p = kmalloc(sizeof(struct probe) * n, GFP_KERNEL);

 50     /* [cgw]: 分配失败*/

 51     if (p == NULL)

 52         return -ENOMEM;

 53     /* [cgw]: 填装n个struct probe,对应n个主设备号

 54           * 

 55           */

 56     for (i = ; i < n; i++, p++) {

 57         p->owner = module;

 58         p->get = probe;

 59         p->lock = lock;

 60         p->dev = dev;

 61         p->range = range;

 62         p->data = data;

 63     }

 64     /* [cgw]: 进入临界区*/

 65     mutex_lock(domain->lock);

 66     /* [cgw]: 这里p -= n是因为,在以上for循环中,p++了n次 */

 67     for (i = , p -= n; i < n; i++, p++, index++) {

 68         /* [cgw]: 根据当前索引,从probes[]中

 69               * 取出一个probe

 70               */

 71         struct probe **s = &domain->probes[index % ];

 72         /* [cgw]: probe是一个链表,每个新加入的节点,

 73           * 按照其range的大小,从小到大排列,即头结点的

 74           * range是最小的

 75           */

 76         while (*s && (*s)->range < range)

 77             /* [cgw]: 继续查找下一个probe,直到其range大于

 78                       * 或等于新加入probe的range为止

 79                   */

 80             s = &(*s)->next;

 81         /* [cgw]: 找到了一个probe,其range大于或等于新加入

 82               * probe的range,把这个新加入的probe下一节点指向

 83               * 这个probe节点

 84               */

 85         p->next = *s;

 86         /* [cgw]: 新加入的节点代替旧的位置 */

 87         *s = p;

 88     }

 89     /* [cgw]: 退出临界区*/

 90     mutex_unlock(domain->lock);

 91     return ;

 92 }

 93 

 94 void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range)

 95 {

 96     /* [cgw]: 计算MAJOR(dev)到MAJOR(dev + range - 1)有几个

 97           * 主设备,由于主设备号都一样,所以这里n = 1

 98           */

 99     unsigned n = MAJOR(dev + range - ) - MAJOR(dev) + ;

     /* [cgw]: 以主设备号为索引 */

     unsigned index = MAJOR(dev);

     unsigned i;

     struct probe *found = NULL;

     /* [cgw]: 主设备超出255个 */

     if (n > )

         n = ;

     /* [cgw]: 进入临界区*/

     mutex_lock(domain->lock);

     

     for (i = ; i < n; i++, index++) {

         struct probe **s;

         for (s = &domain->probes[index % ]; *s; s = &(*s)->next) {

             struct probe *p = *s;

             /* [cgw]: 找到这个设备,并且其对应的次设备号个数也匹配 */

             if (p->dev == dev && p->range == range) {

                 /* [cgw]: 这个设备对应的节点,被下一节点取代,即移除

                       * 这个节点

                       */

                 *s = p->next;

                 /* [cgw]: 记录这个节点 */

                 if (!found)

                     found = p;

                 break;

             }

         }

     }

     /* [cgw]: 退出临界区*/

     mutex_unlock(domain->lock);

     /* [cgw]: 释放这个节点对应的内存空间 */

     kfree(found);

 }

 

 struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index)

 {

     struct kobject *kobj;

     struct probe *p;

     unsigned long best = ~0UL;

 

 retry:  /* [cgw]: 重试 */

     /* [cgw]: 进入临界区 */

     mutex_lock(domain->lock);

     /* [cgw]: 以主设备号为索引,从probes数组取出一个probe */

     for (p = domain->probes[MAJOR(dev) % ]; p; p = p->next) {

         struct kobject *(*probe)(dev_t, int *, void *);

         struct module *owner;

         void *data;

 

         /* [cgw]: 取出的这个probe对应的设备号大于要查找的设备号

                   * 或 这个probe对应的设备号的最大次设备号小于要查找的设备号

                   * 即不在查找范围内,那么返回,继续取出下一个probe

                   */

         if (p->dev > dev || p->dev + p->range -  < dev)

             continue;

         /* [cgw]: 连续的次设备号个数超过最大范围,出错

           */

         if (p->range -  >= best)

             break;

         /* [cgw]: 模块引用失败???? */

         if (!try_module_get(p->owner))

             continue;

         /* [cgw]: 到此,找到了我们想要的那个probe,接着提取它的值 */

         owner = p->owner;

         data = p->data;

         probe = p->get;

         best = p->range - ;

         /* [cgw]: 计算这个要找的设备的次设备号,相对于找到的probe对应

           * 设备号的次设备号的偏移,因为找到的probe对应设备号的次设备号

           * 是这个设备的次设备号基址

           */

         *index = dev - p->dev;

         /* [cgw]: 未搞明白这个判断的意思 */

         if (p->lock && p->lock(dev, data) < ) {

             /* [cgw]: 放弃模块使用权???? */

             module_put(owner);

             continue;

         }

         /* [cgw]: 退出临界区 */

         mutex_unlock(domain->lock);

         /* [cgw]: 调用probe的实现函数,并返回对应的kobj */

         kobj = probe(dev, index, data);

         /* Currently ->owner protects _only_ ->probe() itself. */

         /* [cgw]: 放弃模块使用权???? */

         module_put(owner);

         /* [cgw]: 获得kobj,退出 */

         if (kobj)

             return kobj;

         goto retry;

     }

     /* [cgw]: 退出临界区 */

     mutex_unlock(domain->lock);

     return NULL;

 }

 

 struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct mutex *lock)

 {

     /* [cgw]: 分配一个struct kobj_map内存空间 */

     struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);

     /* [cgw]: 分配一个struct probe指针内存空间 */

     struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL);

     int i;

 

     /* [cgw]: 分配失败 */

     if ((p == NULL) || (base == NULL)) {

         /* [cgw]: 释放内存空间 */

         kfree(p);

         kfree(base);

         return NULL;

     }

     /* [cgw]: 设置默认设备号为1,连续range个次设备,设置probe的实现

           * 函数(回调)

           */

     base->dev = ;

     base->range = ~;

     base->get = base_probe;

     /* [cgw]: 设置probes数组的初始值 */

     for (i = ; i < ; i++)

         p->probes[i] = base;

     p->lock = lock; 

219     return p;

220 }

map.c 添加注释的更多相关文章

  1. Spark通过修改DataFrame的schema给表字段添加注释(转载)

    转载自:https://www.jianshu.com/p/e4c90dc08935 1.需求背景 通过Spark将关系型数据库(以Oracle为例)的表同步的Hive表,要求用Spark建表,有字段 ...

  2. 在C#里面给PPT添加注释

    平常开会或者做总结报告的时候我们通常都会用到PowerPoint演示文稿,我们可以在单个幻灯片或者全部幻灯片里面添加注释,这样观众可以从注释内容里面获取更多的相关信息. 有些朋友不清楚如何在幻灯片里面 ...

  3. kobject.c 添加注释

    最近结合<Linux Device Drivers>对kobject的理解,对kobject.c文件添加注释,仅供参考! 1 /**  2  *    populate_dir - pop ...

  4. 在Excel里用vba给合并的单元格添加注释

    Excel里使用VBA对已经合并的单元格添加注释,直接使用AddComment会报: 运行时错误 '1004':应用程序定义或者对象定义错误 找了很多文章都没找到怎么解决,最后发现在AddCommen ...

  5. VS 自动添加注释

    现在大多数公司都规定程序员在程序文件的头部加上版权信息,这样每个人写的文件都可以区分开来,如果某个文件出现问题就可以快速的找到文件的创建人,用最短的时间来解决问题,常常是以下格式: //======= ...

  6. EF架构~为EF DbContext生成的实体添加注释(T5模板应用)

    回到目录 相关文章系列 第八回 EF架构~将数据库注释添加导入到模型实体类中 第二十一回  EF架构~为EF DbContext生成的实体添加注释(T4模板应用) 第二十二回EF架构~为EF DbCo ...

  7. svn 强制用户添加注释 和 允许用户修改注释

    当我们用TortoiseSVN提交代码时,有很多人不喜欢写注释,导致以后代码版本多,也不清楚哪个版本到底改了什么东西.所以在提交的时候,我会强制要求添加注释.这是如何实现的?这个话题就涉及到了svn的 ...

  8. Eclipse添加注释简介

    (1)在方法或者属性上面添加注释:在方法或者属性字段的上面一行输/**,然后回车.一般情况下添加的注释格式如下所示,当然注释的格式是可以修改的:   1 2 3 4 5 /**   * @param ...

  9. matlab取消和添加注释以及一些快捷键

    1 matlab中关于注释: 多行注释: 选中要注释的若干语句,工具栏菜单Text->Comment,或者鼠标右击选"Comment",或者快捷键Ctrl+R 取消注释: 选 ...

随机推荐

  1. Block知识点总结

    block的作用 block用于保存一段代码 在适当的时候再使用  它是一种数据类型 block的定义格式: 返回值  (^block变量名)(形参列表) = ^(形参列表) { 需要执行的代码}; ...

  2. [Asp.net 5] Localization-简单易用的本地化

    本地化也叫国际化,就是做多语言程序时,可以一键式将当前语言切换到另外一种语言.对于跨国企业或者和国外有业务往来的公司特别重要:就算一个普通公司的门户如果支持中.英.繁体,也会让人觉得高大上.有没有呀, ...

  3. 基于Metronic的Bootstrap开发框架经验总结(12)--页面链接收藏夹功能的实现

    在一个系统里面,往往有很多菜单项目,每个菜单项对应一个页面,一般用户只需要用到一些常用的功能,如果每次都需要去各个层次的菜单里面去找对应的功能,那确实有点繁琐.特别是在菜单繁多,而客户又对系统整体不熟 ...

  4. jQuery实现AJAX定时刷新局部页面实例

    本篇文章通过两种方法实例讲解ajax定时刷新局部页面,当然方法有很多种,也可以不使用ajax来刷新页面,可以使用jquery中的append来给指定内容加东西,但是都不太实用,最实用的方法还是ajax ...

  5. C# DataGridView中指定的单元格不能编辑

    注意:DataGridView控件是从.NET Framework 2.0版本开始追加的. ReadOnly属性的使用 DataGridView内所有的单元格不能编辑 当DataGridView.Re ...

  6. Unity3D 5.x 交互功能 - 光线投射、碰撞设置

    1,光线投射碰撞:第一人称视线在预置范围内(如3米)和看到的物体发生碰撞 ① 检测光线投射碰撞的脚本添加在第一人称FPSController上 #pragma strict private var c ...

  7. html节点属性操作

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. java web学习总结(十三) -------------------使用Session防止表单重复提交

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...

  9. 十一个行为模式之观察者模式(Observer Pattern)

    定义: 定义对象之间一种一对多的关系,当被观察者状态变化时,可以自动地通知观察者并执行相关的业务操作.观察者模式又被称为发布-订阅模式等. 结构图: Subject:抽象主题类,定义了所有被观察类的通 ...

  10. PowerDesigner16 基本使用教程

    一.基本概念 概念数据模型也称信息模型,它以实体-联系(Entity-RelationShip,简称E-R)理论为基础,并对这一理论进行了扩充. 它从用户的观点出发对信息进行建模,主要用于数据库的概念 ...