Типы и атрибуты файлов
Важный аспект дизайна файловой системы и ОС - следует ли поддерживать и распознавать типы файлов. Если да, то это может помочь правильному функционированию ОС, например не допустить вывода на принтер бинарного файла.
К типам файлов, поддерживаемых современными ОС, относят регулярные (обычные) файлы и директории. Обычные (регулярные) файлы содержат пользовательскую информацию. Директории (справочники, каталоги) - системные файлы, поддерживающие структуру файловой системы. В каталоге содержится перечень файлов, входящих в него, и устанавливается соответствие между файлами и их характеристиками (атрибутами). Мы будем рассматривать директории ниже.
Напомним, что хотя внутри подсистемы управления файлами обычный файл представляется в виде набора блоков внешней памяти, для пользователей обеспечивается представление файла в виде линейной последовательности байтов. Такое представление позволяет использовать абстракцию файла при работе с внешними устройствами, при организации межпроцессных взаимодействий и т.д. Поэтому, иногда к файлам приписывают другие объекты ОС, например, специальные символьные файлы и специальные блочные файлы, именованные каналы и сокеты, имеющие файловый интерфейс. Эти объекты рассмотрены в других разделах данного курса.
Далее, главным образом, речь пойдет об обычных файлах.
Обычные (или регулярные) файлы реально представляют собой набор блоков (возможно, пустой) на устройстве внешней памяти, на котором поддерживается файловая система. Такие файлы могут содержать как текстовую информацию (обычно в формате ASCII), так и произвольную двоичную информацию.
Обычные регулярные файлы бывают - ASCII и бинарные.
ASCII файлы содержат строки текста, которые можно распечатать, увидеть на экране или редактировать обычным текстовым редактором.
Другой тип файлов - бинарные файлы, означает, что это не ASCII файлы. Обычно они имеют некоторую внутреннюю структуру. Например, выполнимый Unix файл имеет пять секций: заголовок, текст, данные, биты реаллокации и символьную таблицу. ОС выполняет файл, только если он имеет нужный формат. Другим примером бинарного файла может быть архивный файл.
Типизация файлов не слишком строгая.
Обычно прикладные программы, работающие с файлами, распознают тип файла по его имени в соответствии с общепринятыми соглашениями. Например, файлы с расширениями .c, .pas, .txt - ASCII файлы, файлы с расширениями .exe - выполнимые, файлы с расширениями .obj, .zip - бинарные и т.д.
Помимо имени ОС часто связывают с каждым файлом и другую информацию, например дату модификации, размер и т.д. Эти другие характеристики файлов называются атрибутами. Список атрибутов может варьироваться от одной ОС к другой. Он может включать: атрибуты защиты, пароль, имя создателя, флаги скрытости, архивности, системности, бинарности, тип доступа, длину записи, позицию ключа, время, дату, размер и т.д.
Эта информация обычно хранится в структуре директорий (см. раздел реализация директорий) или других структурах, обеспечивающих доступ к данным файла.
Доступ к файлам
Для использования информации, хранимой в файлах, она должна быть считана в память компьютера. Есть несколько способов доступа к файлам.
Ранние ОС давали только один способ доступа - последовательный (модель ленты). Записи считывались в порядке поступления. Текущая позиция считывания могла быть возвращена к началу файла (rewind). Вместе с магнитными барабанами и дисками появились файлы с прямым (random) доступом. Для специфицирования места, с которого надо начинать чтение используются два способа: с начала, или с текущей позиции, которую дает операция seek.
Последовательный доступ базируется на модели ленты и работает как на устройствах последовательного доступа, так и прямого. Это наиболее общая модель. Организация прямого доступа существенна для многих приложений, например, для систем управления базами данных.
Не все системы поддерживают оба (последовательный и прямой) метода доступа. Последовательный доступ легко эмулировать при помощи прямого, однако реализация прямого доступа через последовательный была бы очень неэффективной.
Помимо прямого и последовательного существуют и другие методы доступа. Обычно они включают конструирование индекса файла и базируются на прямом методе доступа. Для поиска записи вначале происходит обращение к индексу, где находится указатель на нужную запись.
Предположим, что имеется большой файл, содержащий разнообразные сведения о студентах, состоящих из записей с несколькими полями, и возникает задача организации быстрого поиска по одному из полей, например по фамилии студента.
Рис. 3.2.2 Пример организации индекса для последовательного файла
Рис. иллюстрирует решение данной проблемы - организацию индексно-последовательного метода доступа к фалу.
Способ выделения дискового пространства при помощи индексных узлов, применяемый в ряде ОС (Unix и ряде других, см. следующую главу) может служить другим примером организации индекса.
В этом случае ОС использует древовидную организацию блоков, при которой блоки, составляющие файл, являются листьями дерева, а каждый внутренний узел содержит указатели на множество блоков файла. Для больших файлов индекс может быть слишком большим. В этом случае создают индекс для индексного файла (блоки промежуточного уровня или блоки косвенной адресации).
Операции над файлами.
Операционная система должна предоставить в распоряжение пользователя набор операций для работы с файлами, реализованных через системные вызовы. Чаще всего при работе с файлом пользователь выполняет не одну, а несколько операций. Во-первых, нужно найти данные файла и его атрибуты по его символьному имени, во-вторых, считать необходимые атрибуты файла в отведенную область оперативной памяти и проанализировать права пользователя на выполнение требуемой операции. Затем выполнить операцию, после чего освободить занимаемую данными файла область памяти. Рассмотрим в качестве примера основные файловые операции ОС Unix:
§ Create. Создание файла, не содержащего данных. Смысл данного вызова - объявить, что файл существует и присвоить ему ряд атрибутов.
§ Delete. Удаление файла и освобождение занятого им дискового пространства.
§ Open. Перед использованием файла процесс должен его открыть. Цель данного системного вызова разрешить системе проанализировать атрибуты файла и проверить права доступа к файлу, а также считать в оперативную память список адресов блоков файла для быстрого доступа к его данным.
§ Close. Если работа с файлом завершена, его атрибуты и адреса блоков на диске больше не нужны. В этом случае файл нужно закрыть, чтобы освободить место во внутренних таблицах файловой системы.
§ Seek. Дает возможность специфицировать место внутри файла, откуда будет производиться считывание (или запись) данных, то есть задать текущую позицию.
§ Read. Чтение данных из файла. Обычно это происходит с текущей позиции. Пользователь должен задать объем считываемых данных и предоставить буфер для них.
§ Write. Запись данных в файл с текущей позиции. Если текущая позиция находится в конце файла, его размер увеличивается, в противном случае запись осуществляется на место имеющихся данных, которые, таким образом, теряются.
§ Get attributes. Предоставляет процессам нужные им сведения об атрибутах файла. В качестве примера можно привести, утилиту make, которая использует информацию о времени последней модификации файлов.
§ Set attributes. Дает возможность пользователю установить некоторые атрибуты. Наиболее очевидный пример - установка режима доступа к файлу.
§ Rename. Возможность переименования файла создает дополнительные удобства для пользователя. Данная операция может быть смоделирована копированием данного файла в файл с новым именем и последующим его удалением.
Существует два способа выполнить последовательность действий над файлами [30]:
В первом случае для каждой операции выполняются как универсальные, так и уникальные действия (схема stateless). Например, последовательность операций может быть такой: open, read1, close, ... open, read2, close, ... open, read3, close.
Альтернативный способ, это когда универсальные действия выполняются в начале и в конце последовательности операций, а для каждой промежуточной операции выполняются только уникальные действия. В этом случае последовательность вышеприведенных операций будет выглядеть так: open, read1, ... read2, ... read3, close.
Большинство ОС использует второй способ, как более экономичный и быстрый. Первый способ более устойчив к сбоям, поскольку результаты каждой операции становятся независимыми от результатов предыдущей операции, поэтому он иногда применяется в распределенных системах (например, Sun NFS).