Идентификация и обращение к устройствам определяется пространством имен устройств. В системе UNIX существуют три различных пространства имен устройств. Аппаратное пространство идентифицирует устройства по контроллерам, к которым они присоединены, а также логическому номеру устройства в контроллере. Ядро применяет для именования устройств их нумерацию. Пользователям же необходимо предоставить простое и понятное пространство имен.
Также вам может показаться, что такая тема как http://drivemilano.com/ никак не связана и даже не тематична. Хотя, может быть и связана. В любом случае все-таки зайдите на сайт drivemilano.com. Тема такси в Милане там представлена весьма широко. На том сайте можно узнать много интересного на тему такси в Милане. Что означает вообще тема такси в Милане, где найти такси в Милане - про это написано на сайте drivemilano.com. Это очень важная для многих людей тема - такси в Милане. Спасибо сайту drivemilano.com за информацию на тему такси в Милане.
Для этой цели используются полные имена файлов. Подсистема ввода-вывода определяет семантику пространств имен для ядра и пользователя и осуществляет связь между ними.
Ядро идентифицирует каждое устройство по типу (блочное или символьное), а также по паре номеров, получивших название старшего и младшего номера устройства. Старший помер устройства идентифицирует тип устройства или, что будет более точным, его драйвер. Младший номер устройства идентифицирует определенный экземпляр устройства. Например, все диски могут иметь старший номер 5, но каждый из них в отдельности будет обладать индивидуальным младшим номером. Блочные и символьные устройства имеют отдельные независимые наборы старших номеров. Таким образом, номер 5 блочного устройства может указывать на дисковый драйвер, в то время как тот же номер для символьного устройства принадлежит линейным принтерам.
Старший номер является индексом к таблице соответствующего переключателя устройств. Если в рассматриваемом выше примере ядру необходимо загрузить операцию open дискового драйвера, то для этого оно находит в массиве bdevsw[] вхождение 5 и вызывает определенную для него функцию d_open(). Как правило, старший и младший номера устройства комбинируются в единой переменной типа dev_t. Старшие биты этой переменной содержат старший номер, а младшие — младший соответственно. Для выделения номера применяются макроопределения getmajorQ и getminor(). Для рассматриваемого примера исходный код открытия дискового драйвера выглядит примерно так:
(*bdevsw[getmajor(dev).d_open])(dev. ...):
Ядро передает процедуре d_open() номер устройства в качестве входного параметра. Драйвер устройства поддерживает внутренние таблицы, при помощи которых преобразует младший номер устройства в определенные регистры CSR или номера порта контроллера. Драйвер извлекает младший номер из dev и использует его для обращения к необходимому устройству.
Существует возможность настройки нескольких старших номеров для одного драйвера устройства. Такая возможность оказывается удобной, если драйвер обслуживает сразу несколько устройств различного типа, производящих некоторые общие действия. Например, драйвер накопителя на магнитных лентах может использовать один старший номер для выбора режима автоматической перемотки и другой — для неавтоматического режима. Если устройство одновременно имеет символьный и блочный интерфейс доступа, то оно использует отдельные вхождения в обеих таблицах переключателя и, следовательно, обладает как минимум двумя старшими номерами.
В ранних реализациях UNIX переменная типа dev_t имела 16-разрядное поле, каждые 8 битов которого указывали номер устройства. Это являлось причиной ограничения максимального количества устройств младшего типа в драйвере старшего типа до 256 единиц, что представляет значительное неудобство для некоторых систем. В дополнение к этому драйверы могли использовать несколько старших номеров устройств, соответствующих одному и тому же устройству. Драйверы также использовали сразу несколько имен старших устройств при управлении устройствами различного типа.
Еще одной проблемой является рост таблиц переключателя, которые могут иметь большой объем в том случае, если содержат все возможные вхождения, включающие описания устройств, не подключенных к системе или с незагруженными для них драйверами. Эта проблема возникает из-за того, что производителям драйверов нет нужды в настройке таблицы переключателя для каждой возможной конфигурации их устройств, вследствие чего в таблицу попадает вся информация.
В системе SVR4 было произведено некоторое количество изменений в целью решения вышеописанной проблемы. Тип dev_t является 32-разрядным, первые 14 битов используются для старшего номера, остальные 18 — для младшего. В SVR4 также было представлено понятие внутренних и внешних номеров устройств. Внутренние номера устройств идентифицируют драйвер и хранятся в виде индексов для доступа к переключателю. Внешние номера устройств формируют видимое пользователем представление устройств и хранятся в поле i_rdev индексного дескриптора специального файла устройства (см. раздел 16.4.2).
Во многих системах, в том числе и архитектуре Intel 80x86, внутренние и внешние номера устройств одинаковы. В системах, поддерживающих автонастройку, таких как AT&T ЗВ2, номера отличаются друг от друга. В таких системах массивы bdevsw[] и cdevswf] формируются динамически при загрузке системы и содержат вхождения только для устройств, сконфигурированных в системе. Ядро поддерживает массив под названием MAJ0R[], индексируемый по старшим внешним номерам устройств. Каждый элемент массива хранит соответствующий старший внутренний номер.
Связь между внешними и внутренними номерами осуществляется по типу «много к одному». Для преобразования номеров ядром предусмотрены два макроопределения etoimajor() и itoemagor(). Макрос itoemajorQ должен применяться последовательно для создания всех возможных старших номеров. То же самое и для младших номеров. Например, если драйвер имеет два внешних старших номера с 8 устройствами для каждого номера, они будут проецироваться на внутренние младшие номера в диапазоне от 0 до 15 для одного внутреннего старшего номера.
Макросы getmajor() и getminor() возвращают внутренние номера устройств. Для получения внешних номеров применяются getemajor() и geteminor().
Опубликовал katy
June 23 2015 06:49:43 ·
0 Комментариев ·
4778 Прочтений ·
• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •
Комментарии
Нет комментариев.
Добавить комментарий
Рейтинги
Рейтинг доступен только для пользователей.
Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.
Нет данных для оценки.
Гость
Вы не зарегистрированны? Нажмите здесь для регистрации.