Лекции по операционным системам (1114687), страница 39
Текст из файла (страница 39)
Отметим, что модели RAID нулевого и первого уровней могут реализовываться программным способом.
Следующие две модели (RAID 2, Рис. 143., и RAID 3, Рис. 144.) — это модели с т.н. синхронизированными головками, что, в свою очередь, означает, что в массиве используются не независимые устройства, а специальным образом синхронизированные. Эти модели обычно имеют полосы незначительного размера (например, байт или слово). Данные модели содержат избыточную информацию, позволяющие восстановить данные в случае выхода из строя одного из устройств. В частности, RAID 2 использует коды Хэмминга (т.е. коды, исправляющие одну ошибку и выявляющие двойные ошибки). Модель RAID 3 более проста, она основана на четности с чередующимися битами. Для этого один из дисков назначается для хранения избыточной информации — полос, дополняющих до четности соответствующие полосы на других дисках (т.е., по сути, в каждой позиции должно быть суммарное число единиц на всех дисках должно быть четным). И в том, и в другом случае при сбое одного из устройства за счет избыточной информации можно восстановить потерянные данные.
-
RAID 2. Избыточность с кодами Хэмминга (Hamming, исправляет одинарные и выявляет двойные ошибки).
-
RAID 3. Четность с чередующимися битами.
RAID 4 является упрощением RAID 3 (Рис. 145.). Это массив несинхронизированных устройств. Соответственно, появляется проблема поддержания в корректном состоянии диска четности. Для этого каждый раз происходит пересчет по соответствующей формуле.
Модели RAID 5 (Рис. 146.) и RAID 6 (Рис. 147.) спроектированы так, чтобы повысить надежность системы по сравнению с RAID 3 и 4 уровней. Опасно оказывается хранить важную информацию (в данном случае полосы четности) на одном носителе, т.к. при каждой записи происходит всегда обращение к одному и тому же устройству, что может спровоцировать его скорейший выход из строя. Надежнее разнести служебную информацию по разным дискам. Соответственно, RAID 5 распределяет избыточную информацию по дискам циклическим образом, а RAID 6 использует двухуровневую избыточную информацию (которая также разнесена по дискам).
-
RAID 4.
-
RAID 5. Распределенная четность (циклическое распределение четности).
-
RAID 6. Двойная избыточность (циклическое распределение четности с использованием двух схем контроля; требуется N+2 диска).
6.2Работа с внешними устройствами в ОС Unix
6.2.1Файлы устройств, драйверы
Как уже неоднократно упоминалось, одной из основных особенностей ОС Unix является концепция файлов: практически все, с чем работает система, представляется в виде файлов. Внешние устройства не являются исключением и также представлены в системе в виде специальных файлов устройств, хранимых обычно в каталоге /dev.
С точки зрения интерфейсов организации работы с внешними устройствами система делит абсолютно все устройства на две категории: байт-ориентированные и блок-ориентированные устройства. С блок-ориентированными устройствами обмен осуществляется порциями данных фиксированной длины, называемыми блоками. Обычно размер блока кратен степени двойки, а зачастую кратен 512 байтам. Все остальные устройства относятся к байт-ориентированным. Такие устройства позволяют осуществлять обмен порциями данных произвольного размера (от 1 байта до некоторого k). Надо отметить, что к байт-ориентированным устройствам помимо физических устройств, с которыми можно осуществлять обмен, могут относиться устройства, с которыми обмен не осуществим. Примером такого устройства может служить таймер: реально обмены с таймером не происходят, он используется для генерации в системе через определенные промежутки времени прерываний, но относится таймер именно к байт-ориентированным устройствам.
Но, говоря о блок- и байт-ориентированных устройствах, следует помнить, что за регистрацию устройств в системе в конечном счете отвечает драйвер устройства: именно он определяет тип интерфейса устройства. Бывают ситуации, когда одно и то же устройство рассматривается системой и как байт-ориентированное, и как блок-ориентированное. В качестве примера можно привести оперативную память. Заведомо ОЗУ является байт-ориентированным устройством, но организации обменов или при развертывании в оперативной памяти виртуальной файловой системы ОЗУ может рассматриваться уже как блок-ориентированное устройство. Также отметим, что априори считается, что те устройства, на которых может располагаться файловая система, являются блок-ориентированными.
Рассмотрим системную организацию информации, необходимой для управления внешними устройствами. Как упоминалось выше, в системе имеется специальный каталог устройств, в котором располагаются файлы особого типа — специальные файлы устройств. Эти файлы обеспечивают решение следующих задач:
-
именование устройств (если быть более точными, то именование драйвера устройства);
-
связывание выбранного для именования устройства имени с конкретным драйвером.
Соответственно, структурная организация файлов устройств отличается от организации, например, регулярных файлов. Специальные файлы устройств не имеют блоков файла, хранимых в рабочем пространстве файловой системы. Вся содержательная информация файлов данного типа размещается исключительно в соответствующем индексном дескрипторе. Индексный дескриптор состоит из перечня стандартных атрибутов файла, среди которых, в частности, указывается тип этого файла, а также включает в себя некоторые специальные атрибуты. Эти атрибуты содержат следующие поля: тип файла устройства (блок- или байт-ориентированное), а также еще 2 поля, позволяющие осуществлять работу с конкретным драйвером устройства, — это т.н. старший номер и младший номер. Старший номер (major number) — это номер драйвера в соответствующей типу файла устройства таблице драйверов. А младший номер (minor number) — это некоторая дополнительная информация, передаваемая драйверу при обращении. За счет этого реализуется механизм, когда один драйвер может управлять несколькими сходными устройствами.
6.2.2Системные таблицы драйверов устройств
Для регистрации драйверов в системе используются две системные таблицы: таблицы блок-ориентированных устройств — bdevsw, и таблица байт-ориентированных устройств — cdevsw. Соответственно, старший номер хранит ссылку на драйвер, хранящийся в одной из таблиц; тип таблицы определяется типом файла устройств.
Каждая запись этих таблиц содержит структуру специального формата, называемую коммутатором устройства. Коммутатор устройства хранит указатели на всевозможные точки входа (т.е. реализуемые функции) в соответствующий драйвер, либо же в соответствующей записи таблицы вместо указанной структуры хранится специальная ссылка-заглушка на точку ядра.
Стоит отметить следующие типовые имена точек входа в драйвер:
-
βopen(), βclose();
-
βread(), βwrite();
-
βioctl();
-
βintr().
Символ β является аббревиатурой имени устройства: обычно в Unix-системах для именования устройства используют двухсимвольные имена. Например, lp — принтер, mt — магнитная лента, и т.п.
В общем случае система специфицирует наиболее полный набор функций, который может предоставить драйвер пользователю. Если какая-либо функция отсутствует, то на ее месте в коммутаторе может стоять заглушка. Заглушки могут быть двух типов: заглушка типа nulldev(), которая при обращении сразу возвращает управление, и заглушка типа nodev(), которая при обращении возвращает управление с кодом ошибки. Например, для таймера скорее всего будут отсутствовать функции чтения и записи, причем при попытке чтения или записи система должна «ругнуться» (т.е. заглушка типа nodev()).
Некоторые из перечисленных точек входа являются специализированными. С помощью функции βioctl() можно производить разного рода настройки и управление драйвером. Функция βintr() вызывается при поступлении прерывания, ассоциированного с данным устройством.
Традиционно часть функций драйверов может быть реализовано синхронным способом, а другая часть — асинхронным способом. Соответственно, синхронная часть драйвера называется top half, а асинхронная — bottom half.
6.2.3Ситуации, вызывающие обращение к функциям драйвера
Список ситуаций, при которых происходит обращение к функциям драйверов, четко детерминирован. Во-первых, это старт системы и инициализация устройств и драйверов. При старте системы она имеет перечень устройств, которые могут быть к ней подключены. Этот перечень — содержимое каталога /dev. После этого она просматривает данный перечень и определяет те устройства, которые есть в наличии, а затем подключает их посредством вызова соответствующей функции коммутатора (функции βioctl()).
Во-вторых, это обработка запросов на обмен. Если процессу необходимо произвести считывание или запись данных, то в этом случае происходит обращение к соответствующей точке входа в драйвер.
В-третьих, это обработка прерывания, связанного с данным устройством. Например, был инициирован обмен, и он закончился (успешно или неуспешно), или же по линии связи пришел какой-то сигнал, который необходимо обработать. В этом случае возникает прерывание, обработка которого происходит в соответствующем драйвере.
И, в-четвертых, это выполнение специальных команд управления устройством. Функции управления могут быть самыми разными, их наполнение зависит от конкретного устройства и от конкретного драйвера.
6.2.4Включение, удаление драйверов из системы
Изначально Unix-системы предполагали, как и большинство систем, «жесткие» статические встраивание драйверов в код ядра. Это означало, что при добавлении нового драйвера или удалении существующего необходимо было выполнить достаточно трудоемкую операцию перетрансляции (когда ядро создается «с нуля») или, как минимум, перекомпоновку (когда есть готовые объектные модули) ядра. Соответственно, эти операции требовали серьезных навыков от системного администратора. Чтобы минимизировать число перекомпоновок ядра, надо было максимизировать число драйверов, встроенных в систему. Но такая модель была неэффективной, поскольку в системе присутствовали драйверы, которые никак не используются.
Альтернативной моделью, существующей и по сей день, является модель динамического связывания драйверов. В этом случае в системе присутствуют программные средства, позволяющие динамически, «на лету» подключить к операционной системе тот или иной драйвер. Данная модель предполагает решение следующих задач. Во-первых, это задача именования устройства. Во-вторых, инициализация драйвера (т.е. формирование системных областей данных и т.п.) и устройства (приведение устройства в начальное состояние). В-третьих, добавление данного драйвера в соответствующую таблицу драйверов устройств (либо блок-, либо байт-ориентированных). И, наконец, «установка» обработчика прерывания, т.е. предоставление ядру информации, что при возникновении определенного прерывания управление необходимо передать в соответствующую точку входа в данный драйвер.
Для реализации указанной модели в различных системах имеются разные средства: разные системные вызовы и разные, соответственно, команды, при этом обычно присутствуют как команды подключения драйверов, так и симметричные команды удаления драйверов.
6.2.5Организация обмена данными с файлами
В этом разделе мы рассмотрим механизм организации обмена данными с файлами, после чего станет понятным, что происходит в системе, когда один и тот же файл открывается в системе одновременно несколькими процессами, а в каждом из них, возможно, по нескольку раз.
Для организации операций обмена в ОС Unix используются системные таблицы и структуры, часть которых ассоциирована с каждым процессом (т.е. они располагаются в адресном пространстве процесса), а часть — с самой ОС.
Таблица открытых файлов (ТОФ) создается в адресном пространстве процесса. Каждая запись этой таблицы соответствует открытому в процессе файлу. Говоря о номере дескриптора открытого в процессе файла, — т.н. файловый дескриптор — подразумевается соответствующий номер записи в таблице открытых файлов процесса. Размер данной таблицы определяется при настройке операционной системы: этот параметр декларирует предельное количество открытых в одном процессе файлов.
Каждая запись ТОФ содержит целый набор атрибутов, который в данный момент нам не интересен, но в этом наборе имеется один достаточно важный атрибут — это ссылка на номер записи в таблице файлов операционной системы (ТФ). Таблица файлов ОС является системной таблицей, она представлена в системе в единственном экземпляре. В этой таблице происходит регистрация всех открытых в системе файлов.
В таблице файлов ОС помимо прочего содержатся такие атрибуты, как указатель чтения/записи (ссылающийся на позицию в файле, начиная с которой будет происходить, соответственно, чтение или запись), счетчик кратности (речь о нем пойдет ниже) и ссылка на таблицу индексных дескрипторов открытых файлов.
Таблица индексных дескрипторов открытых файлов (ТИДОФ) также является системной структурой данных, содержащей перечень индексных дескрипторов всех открытых в данный момент в системе файлов. Каждая запись этой таблицы содержит актуальную копию открытого в системе индексного дескриптора. Здесь также хранится целый набор параметров, среди которых имеется и счетчик кратности.
Для иллюстрации рассмотрим следующий пример (Рис. 148.). Пускай в системе запущен Процесс1, для которого система при его создании сформировала ТОФ1. Затем этот процесс посредством обращения к системному вызову open() открывает файл с именем name. Это означает, что в свободном месте этой таблицы заводится файловый дескриптор для работы с данным файлом. В этой записи ТОФ хранится ссылка на соответствующую запись в ТФ. Если файл открывается впервые в системе, то в ТФ заводится новая запись для работы с этим файлом. В данной записи хранится указатель чтения/записи, а также коэффициент кратности, который в начале устанавливается в значение 1 — это означает, что с данной записью ТФ ассоциирована единственная запись из какой-либо ТОФ. И, конечно, в данной записи ТФ хранится ссылка на запись в ТИДОФ, содержащую актуальную копию индексного дескриптора обрабатываемого файла. Таблицы ТФ и ТИДОФ хранят оперативную информацию, поэтому они располагаются в ОЗУ. Соответственно, файловая система, работая с блоками открытого файла, оперирует данными, хранимыми именно в ТИДОФ.