Операционные системы. Управление ресурсами


Логическая организация файлов Интерфейсы



7.2. Логическая организация файлов. Интерфейсы

Вне зависимости от логической структуры виртуального файла для получения процессом доступа к данным файла должен быть выполнен системный вызов open: handle = open(fileName, mode)

Здесь fileName - символьное имя, идентифицирующее файл для пользователя, соглашения об именовании файлов обсуждаются в следующем разделе. Режим - mode - задает способ обработки файла (чтение, запись, запись в конец, чтение/запись, синхронное/асинхронное выполнение операций ввода/вывода, параметры буферизации, возможность совместного использования файла процессами т.д.). Возвращаемый манипулятор handle используется процессом для идентификации файла во всех последующих операциях с ним.

Системный вызов: close(handle)

закрывает файл, то есть, заканчивает работу процесса с файлом. Как правило, ОС обеспечивает при завершении процесса автоматическое закрытие всех открытых им файлов.

Синтаксис и семантика системных вызовов, связанных с чтением/ записью и поиском данных в файле, зависит от логической структуры файла. Логические структуры виртуальных файлов прежде всего можно подразделить на байториентированные и записеориентированные.

Байториентированные файлы представляются как линейная последовательность байт, без какого-либо дополнительного структурирования. API байториентированных файлов обеспечивается тремя основными системными вызовами: read(handle,vAddr, byteCounter) write(handle, vAddr, byteCounter) seek (handle, offset, form)

Здесь vAddr - адрес той области в виртуальном адресном пространстве процесса, с которой происходит обмен. За одну операцию обмена читается или пишется заданное byteCounter количество байт. К байториентированным файлам обеспечивается произвольный доступ, для чего вводится понятие файлового курсора - номера того байта файла, который будет читаться/записываться следующим. По умолчанию при открытии файла курсор устанавливается на начало файла и сдвигается при каждой операции read/write на byteCounter. Но системный вызов seek дает процессу возможность установить курсор в произвольную позицию, причем смещение offset может задаваться как от начала файла, так и от его конца или от текущей позиции курсора (это задается параметром from). Возможен также сервисный системный вызов, возвращающий текущее положение курсора. Системный вызов read должен адекватно реагировать на попытку чтения данных за концом файла. Стандартным решением является возврат этим вызовом числа прочитанных байт - при достижении конца файла возвращаемое значение будет меньше, чем byteCounter.

Безусловно, байториентированная организация является наиболее универсальной из всех возможных, так как на неструктурированную последовательность байт приложение может наложить любую собственную логическую структуру. Приведем пример, наверняка известный читателю: MS DOS поддерживает только байториентированную организацию файлов, но системы программирования Pascal (приложения в MS DOS) обеспечивают работу с файлами, состоящими из записей - тип данных file of ... . Байториентированные файлы являются единственной логической файловой структурой, поддерживаемой ОС Unix, и "с подачи" этой системы они включены в стандарт на переносимость ОС.

Альтернативной файловой организацией является записеориентированная. Записеориентированные файлы поддерживает фирма IBM в нескольких поколениях своих ОС для ЭВМ средней и большой мощности. В таких файлах единицей обмена является запись - порция данных, состоящая из одного или нескольких байт и, возможно, имеющая свою внутреннюю структуру. Имеется целый ряд методов логической организации записеориентированных файлов.

Последовательные файлы - файлы, ориентированные на обработку запись за записью - от первой записи до последней. Синтаксис и семантика системных вызовов read и write для таких файлов такие же, как и для байториентированных, но объем данных задается количеством записей, а не байтов. Произвольное позиционирование файлового курсора для последовательных файлов невозможно, но система может предоставлять системные вызовы для сдвига на запись вперед или назад. Последовательные файлы могут состоять из записей фиксированной или переменной длины. В последнем случае либо длина входит в состав записи, как одно из ее полей, либо запись содержит специальный код - признак конца записи.

Файлы прямого доступа - предполагается, что для каждой записи файла имеется логическая идентификация или ключ (key). Доступ производится к произвольной записи файла с указанием ее ключа. Системные вызовы для чтения записи имеют вид: keyRead (handle, key, vAdd) keyWrite (handle, key, vAdd)

Выполнение такого вызова включает в себя позиционирование файлового курсора на запись, определяемую ключом key, и собственно обмен. (Каким образом ключ может использоваться при поиске записи в файле, мы специально рассмотрим ниже.) Ключ может входить в состав записи, как одно из ее полей (например, поле фамилии в списке личного состава), или не содержаться в составе записи (например, ключ - порядковый номер записи).

Файлы комбинированного доступа допускают как прямой доступ по ключу (keyRead/keyWrite), так и последовательный (read/write) в порядке возрастания ключей. Системный вызов, например, для чтения по ключу 'Коваль' обеспечит считывание записи, относящейся к сотруднику Ковалю, последующие системные вызовы последовательного чтения будут считывать записи, относящиеся к сотрудникам, следующим за Ковалем в принятом (например, в алфавитном) порядке.

Какой организации отдать предпочтение - байт- или записеориентированной? Как мы уже отмечали, байториентированная организация гибче, но при ней задача структурирования файла перекладывается на приложения - а задача эта не всегда простая. Фирма IBM, не желая с одной стороны отказываться от преимуществ записеориентированной организации, а с другой - желая обеспечить совместимость своих ОС со стандартами, обеспечивает поддержку обеих структур, и такое решение представляется нам оптимальным.

Интересной, хотя пока несколько экзотической формой являются файлы отображаемого доступа. Такие файлы при открытии отображаются в виртуальное адресное пространство процесса. Операция open может возвращать дескриптор сегмента в виртуальной памяти, и в дальнейшем все манипулирование с данными файла будет выполняться, как манипулирование с данными в памяти. Хотя такое решение является весьма элегантным, его реализация требует значительного расширения разрядности представления виртуального адреса и реализуется пока только в 64-разрядных клонах Unix.









Начало  Назад  Вперед