__register_chrdev_region函数解析
2017-08-23 21:15
141 查看
/* * Register a single major with a specified minor range. * * If major == 0 this functions will dynamically allocate a major and return * its number. * * If major > 0 this function will attempt to reserve the passed range of * minors and will return zero on success. * * Returns a -ve errno on failure. */
static struct char_device_struct * __register_chrdev_region(unsigned int major, unsigned int baseminor, int minorct, const char *name)
/*参数1:主设备号,参数2:次设备号,参数3:要申请号的设备个数,参数4:驱动名称*/ { struct char_device_struct *cd, **cp; /*一个结构体类型的指针,和一个结构体类型的二级指针*/ int ret = 0; int i; cd = kzalloc(sizeof(struct char_device_struct), GFP_KERNEL); //动态申请一个struct char_device_struct大小的内存空间 if (cd == NULL) //如果没有申请成功 return ERR_PTR(-ENOMEM); //返回错误值 mutex_lock(&chrdevs_lock); //锁机制 /*此if语句的目的在于寻找设备号列表中的空的位置*/ /* temporary */ if (major == 0) { //如果主设备号为0 for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) { 从设备号列表的最后一个往前循环 if (chrdevs[i] == NULL) //如果设备列表中i为空 break; //跳出循环 } if (i == 0) { //如果是列表没有空的 ret = -EBUSY; //显然有问题 goto out; //跳转到out } major = i; //把设备列表空位置作为主设备号 ret = major; //存储主设备号 } cd->major = major; //新元素的主设备号赋值 cd->baseminor = baseminor; //新元素的次设备号赋值 cd->minorct = minorct; //新元素的可容纳次设备的数量赋值 strlcpy(cd->name, name, sizeof(cd->name)); //复制名字到新元素 i = major_to_index(major); //主设备号应与列表号一致 /*寻找新元素插入的位置*/ for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next) //第二个表示如果当前元素存在的话 if ((*cp)->major > major || //如果当前元素的主设备号大于要添加的主设备号 ((*cp)->major == major && //当前元素的主设备号等于要添加的主设备号 (((*cp)->baseminor >= baseminor) || //并且次设备号大于等于要添加的次设备号 ((*cp)->baseminor + (*cp)->minorct > baseminor)))) //如果次设备号+申请设备号的数量 > 次设备号 break; //跳出循环 /* Check for overlapping minor ranges. */ if (*cp && (*cp)->major == major) { //如果当前元素存在并且主设备号和要添加的主设备号一致 int old_min = (*cp)->baseminor; //更新旧的最小值,值为当前元素的次设备号 int old_max = (*cp)->baseminor + (*cp)->minorct - 1;//更新旧的最大值,值为当前次设备号+要申请号的设备个数-1,-1是因为从0开始的次设备号 int new_min = baseminor;//新的最小值为要添加的次设备号 int new_max = baseminor + minorct - 1;//新的最大值为要添加的次设备号+要申请号的设备个数-1,-1是因为次设备号从0开始 /* New driver overlaps from the left. */ //新的区间可以在旧的区间的左侧或者右侧 if (new_max >= old_min && new_max <= old_max) { //显然生成的新的最大值必须要大于旧的最大值或者小旧的最小值 ret = -EBUSY; goto out; } /* New driver overlaps from the right. */ if (new_min <= old_max && new_min >= old_min) { //显然生成的新的最小值必须要大于旧的最大值或者小旧的最小值 ret = -EBUSY; goto out; } } /*往链表内添加新元素*/ cd->next = *cp; //新元素的指向当前元素 *cp = cd; //当前元素更新为新元素 mutex_unlock(&chrdevs_lock); //锁机制 return cd; //返回当前元素的结构体指针 out: mutex_unlock(&chrdevs_lock); kfree(cd); return ERR_PTR(ret); }
程序说明:
1.函数传入的参数1:主设备号 2:次设备号 3:申请设备号的设备个数 4:设备名称
2.此函数一开始先动态申请一个内存,用来存储struct char_device_struct这种类型,然后通过各种筛选,寻找链表中要插入的位置,然后判断次设备号是否合法,然后将新元素插入链表
3.函数返回值为新元素的指针,也就是新元素的地址
相关文章推荐
- register_chrdev_region函数解析
- register_chrdev_region函数源码分析
- register_chrdev 深入解析
- register_chrdev_region函数源码分析
- register_chrdev_region函数源码分析
- 驱动学习之register_chrdev_region函数和cdev结构体
- register_chrdev_region函数源码分析
- register_chrdev_region函数源码分析
- int __register_chrdev(unsigned int major, unsigned int baseminor,unsigned int count,
- register_chrdev()与unregister_chrdev()
- register_chrdev和register_chrdev_region
- misc_register、 register_chrdev 的区别总结
- PCIE协议解析 synopsys IP Register配置空间 读书笔记(8)
- register_chrdev_region
- C语言中auto,register,static,const,volatile的区别详细解析
- class_create()和register_chrdev
- register_chrdev深入分析
- 字符设备 register_chrdev_region()、alloc_chrdev_region()区别
- register_chrdev()与unregister_chrdev()
- register_chrdev_region和alloc_chrdev_region