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

  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. mybatis入门基础(三)----SqlMapConfig.xml全局配置文件解析

    一:SqlMapConfig.xml配置文件的内容和配置顺序如下 properties(属性) settings(全局配置参数) typeAiases(类型别名) typeHandlers(类型处理器 ...

  2. uploadify上传错误:uncaught exception: call to startUpload failed原因

    这个不是什么tab的问题,而是可能有多个上传的div或者input(含有相同的name或者ID)导致的 如果有两个不同的上传按钮,那么他们的name,id要设置得不一样. <div id='to ...

  3. N[开源].NET CORE与MySql更配, MySqlSugar ORM框架 3.x

    MySqlSugar 3.X API 作为支持.NET CORE 为数不多的ORM之一,除了具有优越的性能外,还拥有强大的功能,不只是满足你的增,删,查和改.实质上拥有更多你想像不到的功能,当你需要实 ...

  4. ActiveX(二)Js 监听 ActiveX中的事件

    在上一篇随笔:ActiveX(一)第一个简单的Demo 中,已经可以实现 js 单向调用 ActiveX 中的方法,在很多情况下ActiveX中的方法的执行时相对耗时.耗性能的.在这样的情况下.Act ...

  5. touchstart,touchmove,touchend触摸事件的小小实践心得

    近段时间使用html5开发一个公司内部应用,而触摸事件必然是移动应用中所必须的,刚开始以为移动设备上或许也会支持鼠标事件,原来是不支持的,好在webkit内核的移动浏览器支持touch事件,并且打包成 ...

  6. Oracle函数-DECODE

    DECODE翻译为解码或译码,因为它可以把查询结果翻译成令用户容易理解的内容. 语法: expr: 表达式 search:搜索值 result:结果值 default:默认值 DECODE函数的第一个 ...

  7. androidstudio报错

    今天换一下IDE,结果上来就给我报错, androidstudio message:Error:java.lang.UnsupportedClassVersionError: com/android/ ...

  8. PHP运算符

    运算符 PHP运算符可以根据操作数的个数分为一元运算符.二元运算符.三元运算符.一元运算符例如!(取反运算符)或++(加一运算符),PHP支持的大多数运算符都是这种二元运算符,例如+.-.*./等算数 ...

  9. MyBatis的mapper

    在前面的学习中,我们还在写一些接口啊,实现类啊,是不是感觉好low的... 其实,我们是可以不用写接口的实现类的,今天就带着大家一起学习一下,当然,我是回顾的. 看下面的结构,是不是没实现类呢! 源码 ...

  10. 【Java学习系列】第1课--Java环境搭建和demo运行

    本文地址 分享提纲: 1. java环境的搭建 2. java demo代码运行 3.参考文档 本人是PHP开发者,一直感觉Java才是程序的王道(应用广,科班出身),所以终于下决心跟一跟. 主要是给 ...