因此,我目前正在学习如何编写内核模块/设备驱动程序,并正在研究以下实现unregister_chrdev_region
:
https://elixir.bootlin.com/linux/v6.12/source/fs/char_dev.c#L311
/**
* unregister_chrdev_region() - unregister a range of device numbers
* @from: the first in the range of numbers to unregister
* @count: the number of device numbers to unregister
*
* This function will unregister a range of @count device numbers,
* starting with @from. The caller should normally be the one who
* allocated those numbers in the first place...
*/
void unregister_chrdev_region(dev_t from, unsigned count)
{
dev_t to = from + count;
dev_t n, next;
for (n = from; n < to; n = next) {
next = MKDEV(MAJOR(n)+1, 0);
if (next > to)
next = to;
kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
}
}
我不明白的是这一行的检查:
https://elixir.bootlin.com/linux/v6.12/source/fs/char_dev.c#L318
if (next > to) next = to;
据我所知,当循环变量等于上限时,循环已经中断to = from + count
。什么时候我们会遇到条件的情况if (next > to)
?这个条件检查的原因是什么?
unregister_chrdev_region
取消注册一系列设备,但必须按照主要使用方式处理该取消注册__unregister_chrdev_region
。循环处理此问题:n
是当前主要设备范围的开始next = MKDEV(MAJOR(n)+1, 0);
提取设备的主要编号n
,并使用它来计算下一个主要范围的起始next
大于to
,则当前范围完全包含在当前专业内,并且取消注册需要停止在to
而不是next
在所有情况下,
__unregister_chrdev_region
都会被调用来取消注册当前主要范围中剩余的内容,并将next
其设置为下一个主要范围的开始或整个范围的结束,以便循环的下一次迭代处理下一个主要范围,或者如果所有内容都已处理则退出。让我们举个例子:如果你要求取消注册从主设备 1、次设备 512 开始的 1024 个设备:
from
为 1536,count
为 1024to
计算结果为 2560n
是 1536next
计算结果为 2048(大 2)__unregister_chrdev_region
调用来取消注册从 1536 开始的 512 个设备n
是 2048next
计算结果为 3072(大 3)next
设置为to
,并__unregister_chrdev_region
调用以取消注册从 2048 开始的 512 个设备n
是 2560,循环结束你误解了循环的作用!循环不是
其运行
to - from == count
时间恰好为。相反,
在这种情况下,
如果你查看
MKDEV
和的MAJOR
定义,你会发现它扩展为这相当于“向上舍入到 2 20的下一个倍数(即使
n
已经是倍数)”。因此,很有可能在第一次迭代中您的
next
值就已经大于to
!