Ю. Вахалия - UNIX изнутри (2003) (1114670), страница 83
Текст из файла (страница 83)
Проверить поле режима индексного дескриптора с целью обнаружения, что считываемый файл является символьным устройством. 6. Использовать основной номер устройства (хранящийся в индексном дескрипторе) для запроса необходимого элемента таблицы символьных устройств и получения для него элемента структуры сдечм, Элемент представляет собой массив указателей на функции, реализуюшие специфические для данного устройства операции. 7.
Из структуры сдечвн получить указатель на процедуру д геад для используемого устройства. 8. Вызвать операцию д геад для проведения обработки специфичного для конкретного устройства запроса на чтение. Код при этом выглядит следующим образом: гезе11 = 1*(сеечвн(аа5аг~.е геай)(...); где та)ог — основной номер устройства.
9. Разблокировать индексный указатель и произвести возврат функции чтения. Как мы видим, большинство шагов алгоритма являются независимыми от конкретного устройства. Шаги 1 — 4 и 9 как правило применяются и для обычных файлов, следовательно, они независимы от типа файлов. Взаимодействие между ядром и устройствами производится на этапах 7 — 9, при этом необходимые функции извлекаются из таблицы сдечвчг. Операции, зависящие от конкретно используемого устройства, производятся только на шаге 8. Вспомним, что поля таблицы сдечвчг, такие как д геад, определяют абстрактный интерфейс.
Каждое устройство реализует их при помощи различных функций, например 1геад() для линейного принтера или 11геад() для терминала. Основной номер устройства используется как ключ, при помоши которого общая для всех операция д геад преобразуется в функцию, специфичную для устройства. 354 Глава 8.
Базовые элементы и интерфейс файловой системы Используемые принципы можно расширить и на проблему поддержки нескольких файловых систем. Необходимо разделить коды файловой подсистемы на две части: зависимую от файловой системы и независимую от нее. Интерфейс между ними должен быть определен как набор общих функций, вызываемых независимым от файловой системы кодом для проведения манипуляций с файлами и операций доступа. Участок кода, зависящий от файловой системы, реализует специфические функции.
Он неодинаков и пишется для каждого типа файловой системы по отдельности. Базовые конструкции предоставляют механизмы добавления новых файловых систем, а также используются для преобразования абстрактных операций в функции, специфичные для обрабатываемых файлов. ОБЪЕКТНО-ОРИЕНТИРОВАННЫЙ ПОДХОД (ОТСТУПЛЕНИЕ) Интерфейс упобеднз создан на основе концепций объектно-ориентированного программирования (ООП). Позже такой подход был использован и для других участкав ядра О(Ч!Х, таких как управление памятью, коммуникации при помощи сообщений и планирование процессов.
Ознакомимся вкратце с основами ООП в части применения дпя разработки ядра систем О(Ч)Х. Такие технологии обычно реализуются при помощи объектно-ориентированных языков программирования типа С++, но разработчики ОН)Х выбрали для этого язык С из соображений единообразия с кодами остальной части ядра. Объектно-ориентированный подход основан на понятиях класса и обьекта. Класс является сложным типом данных, состоящим из полей данных членов класса и набора их функций. Объект — это элемент класса.
Функции членов класса оперируют с индивидуальными объектами этого класса. Обобщенно каждый член класса (данные или функ. ция) бывает либо открытым (рцЫ)с), либо закрытым (ргма(е), Внешние пользователи класса видят только общедоступные его элементы. Закрытые данные или методы могут быть доступны только другим функциям того же класса. На основе любого класса можно создать один или более порожденных классов, называемых классами-наследниками (рис. 8.7). Класс-наследннк сам по себе может яв.
ляться базовым для последующих классов, порожденных от него. Так формируется иерархия классов. Наследник приобретает все атрибуты (данные и функции) своего базового класса. Более того, в нем могут быть изменены некоторые функции базового класса, — таким образом, класс-потомок может обладать собственными реализациями этих функций. Базовый класс Класс-наслвдник Рис.
8.7. Взаимосвязь между базовым классом и его наследниками В.б. Архитектура чпобедг(э 355 Так как порожденный класс обладает всеми атрибутами базового класса, объект такого типа также является и объектом типа базового класса. Например, класс ойгес1огу (каталог) может являться порожденным классом 11(е (файла). Это означает, что любой каталог является и файлом. Конечно, обратное утверждение не будет верным. не каждый файл представляет собой каталог. Точно так же указатель на объект каталога является и указателем на объект файла.
Атрибуты, добавленные в класс-наследник, невидимы базовым классом. Следовательно, указатель на базовый объект нельзя использовать для доступа к данным или функциям, специфичным для поро:кденного класса. Часто базовый класс используется для задания основных абстракций и определения интерфейса. Специфичные реализации функций для каждого члена класса оформляются в порожденных классах. Таким образом, в классе П1е можно определить функцию сгеате(), но при вызове ее пользователем для произвольного файла загрузятся различные процедуры в зависимости оттого, является ли файл обычным, каталогом, символической ссылкой, файлов устройства и т.
д. Мы вправе вообще не определять функцию оеате() для произвольного файла. Такая функция называется виртуальной функцией. Реализовать вышеописанные объекты можно при помощи языков ООП. Например, на С++ можно определить абстрактный базовый класс как класс, содержащий как минимум одну виртуальную функцию.
Так как базовый класс не будет иметь реализации для этой функции, она не может быть вызвана. Она используется только для порожденных классов, в которых предлагаются различные реализации виртуальных функций. Все объекты являются представителями одного или другого класса-потомка, но пользователь волен управлять ими при помощи указателя базового класса, не обладая знаниями, к какому конкретному классу-наследнику они относятся.
Если для объекта вызывается виртуальная функция, то определение, какую из специфических функций необходимо вызвать, происходит автоматически, в зависимости от класса-наследника данного объекта. Как уже упоминалось ранее, языки, такие как С++ или ЯгпайТа1К, обладают встроенными конструкциями для описания таких понятий, как классы или виртуальные функции.
В языке С эти элементы приходится реализовывать самостоятельно. В следующем разделе мы расскажем об интерфейсе епоое,Мэ, в основу которого положен объектно-ориентированный подход. В.6.3. Краткий обзор интерфейса чпобе/Фа В ядре системы ())ч)1Х файл представлен абстракцией апогее (или у(ггца! поде, виртуальным узлом), файловая система представлена понятием тф (у(ггца1 6!е зузгет). Обе абстракции могут быть реализованы как абстрактный базовый класс, внутри подклассов которого описаны специфические реализации для различных файловых систем, например з5(з, цЬ, ХГ8 или ГАТ (файловая система МВ-РО8). Класс упос(е системы 8Ъ'й4 показан на рис.
8.8. Поля данных базового класса иное(е содержат информацию, не зависящую от определенного типа файловой системы. Функции членов класса могут быть поделены на две категории. В первой категории находится набор виртуальных функций, определяющих зависимый от файловой системы интерфейс, В каждой отдельной файловой системе должны иметься собственные реализации для таких функций.
Ко второй категории относится набор высокоуровневых утилит, используемых другими подсистемами ядра для осуществления действий с файлами. Такие функции вызывают для выполнения задач низкого уровня зависимые от файловой системы процедуры. 356 Глава 8. Базовые элементы и интерфейс файловой системы Поля данных (структура чпоае) ч сочп( ч са(а ч СУРе ч ср ч чгзпоиптеспеге ... Функции (структура чпоеворе) Функции вектора чподвора, зависимые от файловой системы Утилиты и макроопределения Рис. 8.8. Организация чпог)е Базовый класс Уводе имеет два поля, используемые для реализации подклассов.
Первое поле — ч ()ага, является указателем (типа са()()г ~) на закрытую структуру данных, в которой хранятся зависящие от файловой системы данные чпоое, Для файлов з5Ь или цЬ это традиционная структура индексных дескрипторов (по((е. В системе Х5г' используется структура гпо((е, в стрЬ применяется ~щрпо()е и т. д. Так как доступ к этим структурам происходит ие напрямую, а при помощи ч ((а1а, они непрозрачны для базового класса чпоое, а их поля видимы только для функций, являющихся внутренними по отношению к специфичным файловым системам, Поле ч ор указывает на структуру чпо((еорз, состоящую из набора указателей на функции реализации виртуального интерфейса к чпо()е. Поля ч ((ага и ч сй заполняются при инициализации чпос)е, обычно на стадии выполнения системных вызовов преп или сгеа(е.
Когда участок кода, не зависящий от файловой системы, вызывает виртуальную функцию для произвольного чподе, наро изменяет указатель ч ор и вызывает конкретную функцию, относящуюся к определенной реализации файловой системы. Например, операция чОР СЕ05Е позволяет вызвавшему ее процессу закрыть файл, ассоциированный с Уводе. Доступ происходит при помощи макроса, такого как приведен ниже: ()сеГ1пе ЧОР СЕО5Е(чр. ...) (*((чр)->ч ор->чор с)озе))(чр.