Присваивание номеров устройств
Для отслеживания номеров, присвоенных символьным устройствам, ядро ведет хеш-таблицу chrdevs, в которой хранятся интервалы номеров устройств. Два интервала могут иметь один и тот же старший номер, но они не могут пересекаться, и поэтому их младшие номера должны быть разными. Таблица рассчитана на 255 записей, и хеш-функция маскирует четыре старших бита старшего номера. Таким образом старшие номера, меньшие 255, хешируются в разные записи. Каждая запись указывает на первый элемент списка коллизий, упорядоченного по возрастанию старших и младших номеров.
Каждый элемент списка является структурой char_device_struct, поля которой представлены в табл. 13.10.
Существует два метода для присваивания диапазона номеров устройств драйверу символьного устройства. Первый, который следует использовать ДЛЯ всех НОВЫХ драйверов, основан на функциях register_chrdev_region И aiioc_chrdev_region. Он заключается в присваивании драйверу произвольного диапазона номеров устройств. Например, чтобы получить интервал номеров, начинающийся СО значения dev типа dev_t И имеющий ширину size, нужно написать:
register_chrdev_region(dev, size, "foo") ;
Эти функции не вызывают функцию cdev add , так что драйвер устройства должен вызвать ее сам после успешного получения запрошенного интервала.
Второй метод основан на функции register chrdev и состоит в присваивании фиксированного интервала номеров устройств, включающего в себя один старший номер и младшие номера от 0 до 255. В этом случае драйвер не должен вызывать cdev add .
Функции register_chrdev_region и alloc_chrdev_region
Функция register_chrdev_region принимает три параметра: исходный номер устройства (старший и младший номера), размер запрошенного диапазона номеров (то есть количество требуемых младших номеров) и имя драйвера устройства, который запросил диапазон номеров. Функция проверяет, захватывает ли запрошенный диапазон несколько старших номеров, и, если это так,
определяет старшие номера и соответствующие интервалы, покрывающие
весь диапазон. Затем функция вызывает функцию register_chrdev_region
(описанную далее) для каждого из этих интервалов.
Функция aiioc_chrdev_region аналогична предыдущей, но служит для динамического выделения старших номеров. В качестве параметров она принимает исходный младший номер из интервала, размер интервала и имя драйвера устройства. Эта функция тоже вызывает register chrdev region .
Функция register chrdev region ВЫПОЛНЯет следующие деЙСТВИЯ!
1. Выделяет новую структуру char device struct и заполняет ее нулями.
2. Если старший номер из интервала равен нулю, значит, драйвер запросил динамическое выделение старшего номера. Начиная с последней записи в хеш-таблице и следуя в обратном направлении, функция ищет пустой список коллизий (указатель null), который соответствует еще не задействованному старшему номеру. Если пустая запись не найдена, функция возвращает код ошибки6.
3. Инициализирует соответствующие ПОЛЯ структуры char device struct первым номером устройства из интервала, размером интервала и именем драйвера.
4. Вызывает хеш-функцию для вычисления индекса в хеш-таблице по старшему номеру.
5. Проходит по списку коллизий в поисках корректной позиции для новой структуры char device struct. Если по ходу дела обнаруживается интервал, перекрывающийся запрошенным, функция возвращает код ошибки.
6. Вставляет НОВЫЙ дескриптор char device struct в список коллизий.
7. Возвращает адрес нового дескриптора char device struct.
Предыдущая страница | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | Следующая страница