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

  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. maven 插件

    一直没注意看maven执行过程中的打印日志,今天突然发现一段话,说编译以及resource未指定编码,默认gbk.于是,百度了设置编码的方式: <plugin> <groupId&g ...

  2. RECONFIGURE语句会清空计划缓存么?

    几个星期前,有个网友问我一个非常有趣的问题:RECONFIGURE语句会清空计划缓存么?通常我对这个问题的答案是简单的是,但慢慢的我找出了真正的答案是“看情况啦”.我们来看下它,为什么“它看情况”. ...

  3. Moon.Orm 5.0 (MQL版) 欣赏另一种Orm的设计风格----大道至简

    Moon.Orm 5.0(MQL版)使用指南(二) 一.使用sql及存储过程 1)使用List<Dictionary<))) 2)MQL 全面接触

  4. MySQL数据迁移到SQL Server

    数据迁移的工具有很多,基本SSMA团队已经考虑到其他数据库到SQL Server迁移的需求了,所以已经开发了相关的迁移工具来支持. 此博客主要介绍MySQL到SQL Server数据迁移的工具:SQL ...

  5. MapReduce Shuffle过程

    MapReduce Shuffle 过程详解 一.MapReduce Shuffle过程 1. Map Shuffle过程 2. Reduce Shuffle过程 二.Map Shuffle过程 1. ...

  6. Buff系统设计

    我就随便一写,你也就随便一看吧.   什么是BUFF?   或许直接回答这个问题,那么你收获到的答案将是五花八门的.这个问题暂时放下不谈,我们可以去看其他的游戏应该是怎么设计的. 我经常玩的游戏里边B ...

  7. C# 洗牌算法

    最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷 学无止境,精益求精   C#洗牌算法如下: class Program { ...

  8. jquery easyui使用(三)······datagrid加载数据(已解决)

    <div id="table_Data"> </div> $("#table_Data").datagrid({ toolbar: '# ...

  9. LINUX最大线程数及最大进程数

    查看最大线程数: cat /proc/sys/kernel/threads-max ulimit User limits - limit the use of system-wide resource ...

  10. 自己动手C#模拟电梯的运行V1.0

    电梯调度有很多种模式,参见http://www.cnblogs.com/jianyungsun/archive/2011/03/16/1986439.html 1.1先来先服务算法(FCFS) 先来先 ...