I. Элементы архитектуры вычислительных систем

Вид материалаДокументы

Содержание


Формат имен файлов.
Тип файла.
Операции над файлами
Подобный материал:
1   ...   31   32   33   34   35   36   37   38   ...   42

Формат имен файлов.

В различных ФС допустимое имя файла может иметь различную длину, и в нем могут использоваться различные наборы символов. Так, в CP/M и ее потомках MS DOS-DR DOS имена файлов хранятся в 8-битной ASCII-кодировке и имеют длину 11 символов: 8 символов - собственно имя, а 3 - расширение. При этом имя имеет вид "XXXXXXХХ.XXX", но символ '.' не является частью имени - это просто знак препинания. Предполагается, что расширение должно соответствовать типу данных, хранящихся в файле: .SAV будет именем абсолютного загружаемого модуля, .FOR - программы на Фортране, и т.д. В этих системах в именах файлов разрешено использование только букв верхнего регистра, цифр и некоторых печатаемых символов.

Наибольшим либерализмом в смысле имен отличаются ОС семейства Unix, в которых имя файла может состоять из любых символов кодировки ASCII, кроме символов '\000' и '/', например, из восьми символов перевода каретки. При этом '\000' является ограничителем имени, а '/' - разделителем между именем каталога и именем файла. Никакого разделения на имя и расширение нет, и хотя имена файлов с программой на языке C заканчиваются ".c", а объектных модулей - ".o", точка здесь является частью имени. Вы можете создать файл с именем "gcc-2.5.8.tar.gz". В UNIX SVR3 длина имени файла ограничена 14 символами, а в BSD UNIX, Linux и SVR4 - только длиной блока на диске, т.е. 512 байтами или более. При этом нулевой символ считается концом имени в каталоге.

Возможность использования длинных имен файлов, очевидно, приносит ряд преимуществ. В следствие этого многие современные ОС включают поддержку этой возможности. Например, OS/2, использующая файловую систему HPFS (High Performance File System - высокопроизводительная файловая система), поддерживает имена файлов длиной до 256 символов, содержащие печатаемые символы и пробелы. Точка считается частью имени, как и в UNIX, и можно создавать имена, содержащие несколько точек. При этом нужно отметить, что система при поиске файла приводит к одному регистру все алфавитные символы в имени. С одной стороны, это означает дополнительное удобство для пользователя - при наборе имени не нужно заботиться о регистре букв, с другой - пользователь не может создать в одном каталоге файлы "text.txt" и "Text.txt". Из-за этого, например, нельзя использовать принятое в UNIX соглашение о том, что файл на языке C имеет расширение ".c", а на языке C++ - ".C".

Поддержка длинных имен файлов реализована и в наследнике линии CP/M-MS DOS, операционной системе Windows 95.

Некоторые ОС, например, RSX-11 и VMS, поддерживают также номер версии файла. В каталоге может существовать несколько версий файла с одним именем; если номер версии при открытии файла не задается, то открывается последняя версия. Версии файла очень удобны при разработке любых объектов, от программ или печатных плат до книг: если вам не понравились изменения, внесенные вами в последнюю версию, вы всегда можете откатиться назад.

Тип файла.

Первые попытки ассоциировать с файлом признак типа были сделаны еще в 60 гг. При этом идентификатор типа добавлялся к имени файла в виде короткой, но мнемонической последовательности символов - расширения (extension). В большинстве современных ОС расширение отделяется от имени символом '.'. При этом, например, файлы на языке C будут иметь расширение ".c", на языке Pascal - ".pas", а документы в формате LaTeX - ".tex".

В ОС семейства Unix имя файла может содержать несколько символов '.', и, таким образом, файл может иметь несколько каскадированных расширений. Например, файл "main.C" - это программа на языке C++; "main.C.gz" - это программа на языке C++, упакованная архиватором GNU Zip с целью сэкономить место; "main.C.gz.crypt" - это программа, которую упаковали и потом зашифровали, чтобы никто посторонний не смог ее прочитать; наконец, "main.C.gz.crypt.uue" - это упакованная и зашифрованная программа, преобразованная в последовательность печатаемых символов кода ASCII, например, для пересылки по электронной почте.

В принципе, расширения являются вполне приемлемым и во многих отношениях даже очень удобным способом идентификации типа файла. Одно из удобств состоит в том, что для использования этого метода не нужно никаких или почти никаких усилий со стороны ОС: просто программы договариваются интерпретировать имя файла определенным образом.

Однако никакие средства операционной системы не могут навязать прикладным программам правил выбора расширения для файлов данных. Это приводит к неприятным коллизиям. Например, почти все текстовые процессоры от Лексикон до Word 97 включительно используют расширение файла .doc (сокращение от document), хотя форматы файлов у различных процессоров и даже у разных версий одного процессора сильно различаются.

Операции над файлами могут быть разделены на три группы:
  1. операции над файлами, как единым целым (открыть, закрыть, копировать, объединить, переместить, удалить
  2. операции обмена данными между файлом и прикладной программой (чтение/запись)
  3. служебные операции (изменение владельца, переименование, изменение прав доступа или атрибутов, и т.п.)

В стандарте POSIX, например, над файлом определены следующие операции:
  • int open(char * fname, int flags, mode_t mode) Эта операция "открывает" файл, устанавливая соединение между программой и файлом. При этом программа получает дескриптор файла - целое число, идентифицирующее данное соединение. Фактически это индекс в системной таблице открытых файлов для данной задачи. Все остальные операции используют этот индекс для ссылки на файл. Параметр char * fname задает имя файла. int flags - это битовая маска, определяющая режим открытия файла. Файл может быть открыт только на чтение, только на запись и на чтение и запись; кроме того, можно открывать существующий файл, а можно пытаться создать новый файл нулевой длины. Необязательный третий параметр mode используется только при создании файла и задает атрибуты этого файла:
  • off_t lseek(int handle, off_t offset, int whence) Эта операция перемещает указатель чтения/записи в файле. Параметр offset задает количество байт, на которое нужно сместить указатель, а параметр whence - откуда отсчитывать смещение. Предполагается, что смещение можно отсчитывать от начала файла (SEEK_SET), от его конца (SEEK_END) и от текущего положения указателя (SEEK_CUR). Операция возвращает положение указателя, отсчитываемое от начала файла. Таким образом, вызов lseek(handle, 0, SEEK_CUR) возвратит текущее положение указателя, не передвигая его;
  • int read(int handle, char * where, size_t how_much) Операция чтения из файла. Указатель where задает буфер, куда нужно поместить прочитанные данные; третий параметр указывает, сколько данных надо считать. Система считывает требуемое число байт из файла, начиная с указателя чтения/записи в этом файле, и перемещает указатель к концу считанной последовательности. Если файл кончился раньше, считывается столько данных, сколько оставалось до его конца. Операция возвращает количество считанных байт. Если файл открывался только для записи, вызов read возвратит ошибку;
  • int write(int handle, char * what, size_t how_much) Операция записи в файл. Указатель what задает начало буфера данных; третий параметр указывает, сколько данных надо записать. Система записывает требуемое число байт в файл, начиная с указателя чтения/записи в этом файле, заменяя хранившиеся на в этом месте данные, и перемещает указатель к концу записанного блока. Если файл кончился раньше, его длина увеличивается. Операция возвращает количество записанных байт. Если файл открывался только для чтения, вызов write возвратит ошибку;
  • int ioctl(int handle, int cmd, ...);
  • int fcntl(int handle, int cmd, ...) Дополнительные операции над файлом. Первоначально, по-видимому, предполагалось, что ioctl - это операции над самим файлом, а fcntl - это операции над дескриптором открытого файла, но потом историческое развитие несколько перемешало функции этих системных вызовов. Стандарт POSIX определяет некоторые операции как над дескриптором, например дублирование (в результате этой операции мы получаем два дескриптора, связанных с одним и тем же файлом), так и над самим файлом, например, операцию truncate - обрезать файл до заданной длины. В большинстве версий Unix операцию truncate можно использовать и для вырезания данных из середины файла. При считывании данных из такой вырезанной области считываются нули, а сама эта область не занимает физического места на диске.

Важной операцией является блокировка участков файла. Стандарт POSIX предлагает для этой цели библиотечную функцию, но в системах семейства Unix эта функция реализована через вызов fcntl.

Большинство реализаций стандарта POSIX предлагает и свои дополнительные операции. Так, в Unix SVR4 этими операциями можно устанавливать синхронную или отложенную запись и т.д.
  • caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int handle, off_t offset) Отображение участка файла в виртуальное адресное пространство процесса. Параметр prot задает права доступа к отображенному участку: на чтение, запись и исполнение. Отображение может происходить на заданный виртуальный адрес, или же система может выбирать адрес для отображения сама.


3.7 

Файловые системы