map.c 添加注释

来源:互联网 发布:mac安装ie浏览器 编辑:程序博客网 时间:2024/05/18 06:01
/* *  linux/drivers/base/map.c * * (C) Copyright Al Viro 2002,2003 *    Released under GPL v2. * * NOTE: data structure needs to be changed.  It works, but for large dev_t * it will be too slow.  It is isolated, though, so these changes will be * local to that file. */#include <linux/module.h>#include <linux/slab.h>#include <linux/mutex.h>#include <linux/kdev_t.h>#include <linux/kobject.h>#include <linux/kobj_map.h>struct kobj_map {    struct probe {        struct probe *next;        dev_t dev;        unsigned long range;        struct module *owner;        kobj_probe_t *get;        int (*lock)(dev_t, void *);        void *data;    } *probes[255];    struct mutex *lock;};int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,         struct module *module, kobj_probe_t *probe,         int (*lock)(dev_t, void *), void *data){    /* [cgw]: 计算MAJOR(dev)到MAJOR(dev + range - 1)有几个          * 主设备,由于主设备号都一样,所以这里n = 1          */    unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;    /* [cgw]: 以主设备号为索引 */    unsigned index = MAJOR(dev);    unsigned i;    struct probe *p;    /* [cgw]: 主设备超出255个 */    if (n > 255)        n = 255;    /* [cgw]: 分配n个struct probe内存空间*/    p = kmalloc(sizeof(struct probe) * n, GFP_KERNEL);    /* [cgw]: 分配失败*/    if (p == NULL)        return -ENOMEM;    /* [cgw]: 填装n个struct probe,对应n个主设备号          *           */    for (i = 0; i < n; i++, p++) {        p->owner = module;        p->get = probe;        p->lock = lock;        p->dev = dev;        p->range = range;        p->data = data;    }    /* [cgw]: 进入临界区*/    mutex_lock(domain->lock);    /* [cgw]: 这里p -= n是因为,在以上for循环中,p++了n次 */    for (i = 0, p -= n; i < n; i++, p++, index++) {        /* [cgw]: 根据当前索引,从probes[]中              * 取出一个probe              */        struct probe **s = &domain->probes[index % 255];        /* [cgw]: probe是一个链表,每个新加入的节点,          * 按照其range的大小,从小到大排列,即头结点的          * range是最小的          */        while (*s && (*s)->range < range)            /* [cgw]: 继续查找下一个probe,直到其range大于                      * 或等于新加入probe的range为止                  */            s = &(*s)->next;        /* [cgw]: 找到了一个probe,其range大于或等于新加入              * probe的range,把这个新加入的probe下一节点指向              * 这个probe节点              */        p->next = *s;        /* [cgw]: 新加入的节点代替旧的位置 */        *s = p;    }    /* [cgw]: 退出临界区*/    mutex_unlock(domain->lock);    return 0;}void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range){    /* [cgw]: 计算MAJOR(dev)到MAJOR(dev + range - 1)有几个          * 主设备,由于主设备号都一样,所以这里n = 1          */    unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;    /* [cgw]: 以主设备号为索引 */    unsigned index = MAJOR(dev);    unsigned i;    struct probe *found = NULL;    /* [cgw]: 主设备超出255个 */    if (n > 255)        n = 255;    /* [cgw]: 进入临界区*/    mutex_lock(domain->lock);        for (i = 0; i < n; i++, index++) {        struct probe **s;        for (s = &domain->probes[index % 255]; *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) % 255]; 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 - 1 < dev)            continue;        /* [cgw]: 连续的次设备号个数超过最大范围,出错          */        if (p->range - 1 >= best)            break;        /* [cgw]: 模块引用失败???? */        if (!try_module_get(p->owner))            continue;        /* [cgw]: 到此,找到了我们想要的那个probe,接着提取它的值 */        owner = p->owner;        data = p->data;        probe = p->get;        best = p->range - 1;        /* [cgw]: 计算这个要找的设备的次设备号,相对于找到的probe对应          * 设备号的次设备号的偏移,因为找到的probe对应设备号的次设备号          * 是这个设备的次设备号基址          */        *index = dev - p->dev;        /* [cgw]: 未搞明白这个判断的意思 */        if (p->lock && p->lock(dev, data) < 0) {            /* [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 = 1;    base->range = ~0;    base->get = base_probe;    /* [cgw]: 设置probes数组的初始值 */    for (i = 0; i < 255; i++)        p->probes[i] = base;    p->lock = lock;    return p;                                                                                                                   }

原创粉丝点击