为啥内核支持一次调用注册不同主号的设备
Posted
技术标签:
【中文标题】为啥内核支持一次调用注册不同主号的设备【英文标题】:Why kernel supports registering device of different major numbers in one call为什么内核支持一次调用注册不同主号的设备 【发布时间】:2018-12-08 10:08:13 【问题描述】:块设备驱动程序可以调用blk_register_region()
来声称对更大范围的设备号负责。例如,在ramdisk驱动的初始化中,它调用blk_register_region来声明所有可能的ram disk。
static int __init brd_init(void)
// ...
blk_register_region(MKDEV(RAMDISK_MAJOR, 0), 1UL << MINORBITS,
THIS_MODULE, brd_probe, NULL, NULL);
return 0;
像 ramdisk 和 floppy 这样的驱动程序使用它们自己的主设备号(RAMDISK_MAJOR / FLOPPY_MAJOR
在major.h 中定义)注册。但我读了代码
的blk_register_region,发现这个函数支持一次调用注册不同主号的设备。
函数 blk_register_region 简单地包装了 kobj_map。 kobj_map 支持在一次调用中声明多达 255 个主要设备。这种需求从何而来?
void blk_register_region(dev_t devt, unsigned long range, struct module *module,
struct kobject *(*probe)(dev_t, int *, void *),
int (*lock)(dev_t, void *), void *data)
kobj_map(bdev_map, devt, range, module, probe, lock, data);
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)
// calculate the range of major numbers
unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
unsigned index = MAJOR(dev);
unsigned i;
struct probe *p;
if (n > 255)
n = 255;
p = kmalloc(sizeof(struct probe) * n, GFP_KERNEL);
if (p == NULL)
return -ENOMEM;
// ....
非常感谢。
【问题讨论】:
【参考方案1】:But I read the code of blk_register_region and found this function supports registering device of different major numbers in one call
实际情况并非如此。如果您仔细查看代码,它们都会得到相同的主编号(请参阅下面代码中带有我注释的行)。
for (i = 0; i < n; i++, p++)
p->owner = module;
p->get = probe;
p->lock = lock;
p->dev = dev; /* See the assigned device number */
p->range = range;
p->data = data;
关于支持行为的要求,查看thisLWN文章驱动移植:gendisk接口,注册块设备号范围部分。
直接引用文章,
对 add_disk() 的调用会隐式分配一组次要编号 (在给定的主编号下)从 first_minor 到 first_minor+minors-1。如果您的驱动程序必须只响应操作 对于初始化时存在的磁盘,无需担心 进一步关于号码分配。即使是传统的呼吁 register_blkdev() 是可选的,可能很快就会被删除。一些司机, 但是,需要能够对更大范围的 初始化时的设备号。
如果是这种情况,答案是调用 blk_register_region()
这里有几件事需要注意(同样来自文章),
range
是要分配的次要号码的数量。
当调用 blk_register_region() 时,它只是简单地记下所需区域并返回。请注意,在特定区域内可以有多个注册!在查找时,最“具体”的注册(范围最小的注册)获胜。
【讨论】:
谢谢。unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1; if (n > 255) n = 255;
这几行暗示 var n
(主编号的计数)可能大于 255。所以如果 blk_register_region
只处理相同的主编号,那么这些行有什么需要?以上是关于为啥内核支持一次调用注册不同主号的设备的主要内容,如果未能解决你的问题,请参考以下文章