您的位置:首页 > 其它

__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.函数返回值为新元素的指针,也就是新元素的地址
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: