• map.c 添加注释


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

      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[255];
     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 - 1) - MAJOR(dev) + 1;
     40     /* [cgw]: 以主设备号为索引 */
     41     unsigned index = MAJOR(dev);
     42     unsigned i;
     43     struct probe *p;
     44 
     45     /* [cgw]: 主设备超出255个 */
     46     if (n > 255)
     47         n = 255;
     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 = 0; 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 = 0, p -= n; i < n; i++, p++, index++) {
     68         /* [cgw]: 根据当前索引,从probes[]中
     69               * 取出一个probe
     70               */
     71         struct probe **s = &domain->probes[index % 255];
     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 0;
     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 - 1) - MAJOR(dev) + 1;
    100     /* [cgw]: 以主设备号为索引 */
    101     unsigned index = MAJOR(dev);
    102     unsigned i;
    103     struct probe *found = NULL;
    104     /* [cgw]: 主设备超出255个 */
    105     if (n > 255)
    106         n = 255;
    107     /* [cgw]: 进入临界区*/
    108     mutex_lock(domain->lock);
    109     
    110     for (i = 0; i < n; i++, index++) {
    111         struct probe **s;
    112         for (s = &domain->probes[index % 255]; *s; s = &(*s)->next) {
    113             struct probe *p = *s;
    114             /* [cgw]: 找到这个设备,并且其对应的次设备号个数也匹配 */
    115             if (p->dev == dev && p->range == range) {
    116                 /* [cgw]: 这个设备对应的节点,被下一节点取代,即移除
    117                       * 这个节点
    118                       */
    119                 *s = p->next;
    120                 /* [cgw]: 记录这个节点 */
    121                 if (!found)
    122                     found = p;
    123                 break;
    124             }
    125         }
    126     }
    127     /* [cgw]: 退出临界区*/
    128     mutex_unlock(domain->lock);
    129     /* [cgw]: 释放这个节点对应的内存空间 */
    130     kfree(found);
    131 }
    132 
    133 struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index)
    134 {
    135     struct kobject *kobj;
    136     struct probe *p;
    137     unsigned long best = ~0UL;
    138 
    139 retry:  /* [cgw]: 重试 */
    140     /* [cgw]: 进入临界区 */
    141     mutex_lock(domain->lock);
    142     /* [cgw]: 以主设备号为索引,从probes数组取出一个probe */
    143     for (p = domain->probes[MAJOR(dev) % 255]; p; p = p->next) {
    144         struct kobject *(*probe)(dev_t, int *, void *);
    145         struct module *owner;
    146         void *data;
    147 
    148         /* [cgw]: 取出的这个probe对应的设备号大于要查找的设备号
    149                   * 或 这个probe对应的设备号的最大次设备号小于要查找的设备号
    150                   * 即不在查找范围内,那么返回,继续取出下一个probe
    151                   */
    152         if (p->dev > dev || p->dev + p->range - 1 < dev)
    153             continue;
    154         /* [cgw]: 连续的次设备号个数超过最大范围,出错
    155           */
    156         if (p->range - 1 >= best)
    157             break;
    158         /* [cgw]: 模块引用失败???? */
    159         if (!try_module_get(p->owner))
    160             continue;
    161         /* [cgw]: 到此,找到了我们想要的那个probe,接着提取它的值 */
    162         owner = p->owner;
    163         data = p->data;
    164         probe = p->get;
    165         best = p->range - 1;
    166         /* [cgw]: 计算这个要找的设备的次设备号,相对于找到的probe对应
    167           * 设备号的次设备号的偏移,因为找到的probe对应设备号的次设备号
    168           * 是这个设备的次设备号基址
    169           */
    170         *index = dev - p->dev;
    171         /* [cgw]: 未搞明白这个判断的意思 */
    172         if (p->lock && p->lock(dev, data) < 0) {
    173             /* [cgw]: 放弃模块使用权???? */
    174             module_put(owner);
    175             continue;
    176         }
    177         /* [cgw]: 退出临界区 */
    178         mutex_unlock(domain->lock);
    179         /* [cgw]: 调用probe的实现函数,并返回对应的kobj */
    180         kobj = probe(dev, index, data);
    181         /* Currently ->owner protects _only_ ->probe() itself. */
    182         /* [cgw]: 放弃模块使用权???? */
    183         module_put(owner);
    184         /* [cgw]: 获得kobj,退出 */
    185         if (kobj)
    186             return kobj;
    187         goto retry;
    188     }
    189     /* [cgw]: 退出临界区 */
    190     mutex_unlock(domain->lock);
    191     return NULL;
    192 }
    193 
    194 struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct mutex *lock)
    195 {
    196     /* [cgw]: 分配一个struct kobj_map内存空间 */
    197     struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);
    198     /* [cgw]: 分配一个struct probe指针内存空间 */
    199     struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL);
    200     int i;
    201 
    202     /* [cgw]: 分配失败 */
    203     if ((p == NULL) || (base == NULL)) {
    204         /* [cgw]: 释放内存空间 */
    205         kfree(p);
    206         kfree(base);
    207         return NULL;
    208     }
    209     /* [cgw]: 设置默认设备号为1,连续range个次设备,设置probe的实现
    210           * 函数(回调)
    211           */
    212     base->dev = 1;
    213     base->range = ~0;
    214     base->get = base_probe;
    215     /* [cgw]: 设置probes数组的初始值 */
    216     for (i = 0; i < 255; i++)
    217         p->probes[i] = base;
    218     p->lock = lock; 

    219     return p;

    220 }

  • 相关阅读:
    Java中Date日期字符串格式的各种转换
    Redis集群搭建与简单使用
    Java中的Redis应用
    java的linux命令
    Lucene全文检索引擎
    设置Xshell中支持中文
    Java并发Fork-Join框架原理解析
    java线程
    Django-路由层
    Django简介
  • 原文地址:https://www.cnblogs.com/hackfun/p/5696289.html
Copyright © 2020-2023  润新知