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

  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. JavaScript代码模块化的正规方法

    RequireJS-CommonJS-AMD-ES6 Import/Export详解 为什么起了一个这个抽象的名字呢,一下子提了四个名词分别是:RequireJS,CommonJS,AMD,ES6,答 ...

  2. Vue.js说说组件

    什么是组件:组件是Vue.js最强大的功能之一.组件可以扩展HTML元素,封装可重用的代码.在较高层面上,组件是自定义的元素,Vue.js的编译器为它添加特殊功能.在有些情况下,组件也可以是原生HTM ...

  3. C# 文件下载 : WebClient

    最近更新了一个下载小工具,主要提升了下面几点: 1. 在一些分公司的局域网中,连接不上外网 2. 服务器上的文件更新后,下载到的还是更新前的文件 3. 没有下载进度提示 4. 不能终止下载 下面和大家 ...

  4. Visual Studio中安装viemu后,vim vax 快捷键大全

    高效率移动 在插入模式之外 基本上来说,你应该尽可能少的呆在插入模式里面,因为在插入模式里面VIM就像一个“哑巴”编辑器一样.很多新手都会一直呆在插入模式里面,因为这样易于使用.但VIM的强大之处在于 ...

  5. 2>&1 linux

    2>&1使用 2>&1使用 一 相关知识 1)默认地,标准的输入为键盘,但是也可以来自文件或管道(pipe |).2)默认地,标准的输出为终端(terminal),但是也可 ...

  6. MongoDB固定集合(capped collection)

    固定集合指的是事先创建而且大小固定的集合 . 固定集合特性:固定集合很像环形队列,如果空间不足,最早的文档就会被删除,为新的文档腾出空间.一般来说,固定集合适用于任何想要自动淘汰过期属性的场景,没有太 ...

  7. JavaScript进阶篇QA总结

    Q1:常用的运算符有哪些?他们的优先级是怎样的?A1:1.算术运算符:加(+).减(-).乘(×).除(÷),自加一(++),自减一(--):2.比较运算符:大于(>).小于(<).大于等 ...

  8. web前端交互性易用性说明

    总结一下我们在web前端开发过程中总是强调交互性.易用性的情况分析说明.个人觉得web前端的易用交互也就是我们所说人性化操作.不外乎希望达到的效果为:界面风格简洁明了.重点突出:操作简单,直观可见.当 ...

  9. 浅谈HTML5单页面架构(三)—— 回归本真:自定义路由 + requirejs + zepto + underscore

    本文转载自:http://www.cnblogs.com/kenkofox/p/4650310.html 不过,这一篇,我想进一步探讨一下这两个框架的优缺点,另外,再进一步,抛开这两个框架,回到本真, ...

  10. iOS Version 和 Build 版本号

    Version 和 Build 版本号 开发者都知道,无论是对于 iOS 和 Android 的应用,每个应用都有两个不同的版本号.分别是: Version Build(在 Android 上叫 Ve ...