Почему ядро ​​поддерживает регистрацию устройства разных старших номеров за один звонок - PullRequest
0 голосов
/ 29 июня 2018

Драйвер блочного устройства может позвонить blk_register_region(), чтобы взять на себя ответственность за больший диапазон номеров устройств. Например, при инициализации драйвера ramdisk он вызывает blk_register_region для запроса всех возможных ram-дисков.

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 Ответ

0 голосов
/ 02 июля 2018

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;
}

Что касается требования поддерживаемого поведения, отметьте this Статья LWN Портирование драйвера: интерфейс gendisk , раздел Регистрация диапазонов номеров блочных устройств .

Цитирование прямо из статьи,

Вызов add_disk () неявно выделяет набор младших чисел. (под указанным основным номером) от first_minor до first_minor + несовершеннолетние-1. Если ваш водитель должен отвечать только на операции к дискам, которые существуют во время инициализации, не нужно беспокоиться далее о распределении номеров. Даже традиционный призыв к register_blkdev () не является обязательным и может быть удален в ближайшее время. Некоторые водители, Тем не менее, необходимо иметь возможность взять на себя ответственность за более широкий круг номера устройств во время инициализации.

Если это ваш случай, ответ заключается в вызове blk_register_region ()

Несколько вещей, на которые стоит обратить внимание (опять же из статьи),

  • range - количество младших номеров для выделения.
  • Когда вызывается blk_register_region (), он просто запоминает нужную область и возвращает. Обратите внимание, что в одном регионе может быть несколько регистраций! Во время поиска побеждает самая «конкретная» регистрация (с наименьшим диапазоном).
...