__register_chrdev_region函数解析

/*
 * 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.函数返回值为新元素的指针,也就是新元素的地址

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值