Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка по лекциям.doc
Скачиваний:
29
Добавлен:
20.09.2019
Размер:
1.52 Mб
Скачать

6.7. Особенности строения файловых систем для Unix

Принципиальной особенностью файловых систем для Unix является хранение минимальной информации в записях оглавления. Так, в современной расширенной файловой системе для Linux, называемой в сокращении ext2, структура записи каталога описывается структурой

struct dir

{unsigned long inode_num;

unsigned short rec_len;

unsigned short name_len;

char name[256]; /* between 0 and 256 chars */

};

В самой старой файловой системе для Unix, созданной еще в 70-х годах XX века, запись каталога занимала всего 16 байтов, из которых 14 байтов предназначались под имя файла (или каталога), а два оставшихся хранили значение индексного узла (inode).

В современном решении запись каталога имеет переменную длину, определяемую для каждой записи полем rec_len и содержит имя длинной до 255 символов, причем поле name_len задает действительное значение этого имени. Такое решение связано со стремлением, как допускать очень длинные имена и в то же время не делать очень большими записи каталога. По существу, поля rec_len, name_len – вспомогательные, и запись каталога несет все ту же содержательную инфор­ма­цию.

Вся информация о файле (каталоге), за исключением его имени в текущем каталоге, хранится в специализированной структуре файловой системы, называемой индексным узлом (inode). Именно в нем хранится время создания файла (каталога), время последней модификации, время последнего доступа, число ссылок на файл, размер файла. Более подробная информация представлена в описании структуры inode:

typedef struct

{ unsigneg short i_mode; /* File mode */

unsigneg short i_uid; /* Owner Uid */

unsigneg long i_size; /* Size in bytes */

unsigneg long i_atime; /* Access time */

unsigneg long i_ctime; /* Creation time */

unsigneg long i_mtime; /* Modification time */

unsigneg long i_dtime; /* Deletion Time */

unsigneg short i_gid; /* Group Id */

unsigneg short i_links_count; /* Links count */

unsigneg long i_blocks; /* Blocks count */

unsigneg long i_flags; /* File flags */

unsigneg long i_reserved1; /* Reserved 1 */

unsigneg long i_block[15]; /* Pointers to blocks */

unsigneg long i_version; /* File version (for NFS) */

unsigneg long i_file_acl; /* File ACL */

unsigneg long i_dir_acl; /* Directory ACL */

unsigneg long i_faddr; /* Fragment address */

unsigneg char i_frag; /* Fragment number */

unsigneg char i_fsize; /* Fragment size */

unsigneg long i_reserved2[2]; /* Reserved 2 */

} inode;

6.8. Программный опрос файловой системы

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

В ОС Unix операции с каталогом строятся подобно операциям с типизированными файлами, используемыми в Паскале, а именно, вводится указатель на структуру данных, описывающую каталог. Эта структура описана в заголовочном файле dirent.h и имеет имя DIR. Указатель на эту структуру данных используется для получения значения от функции opendir, имеющей прототип

DIR* opendir(char *dirname),

где единственный аргумент задает имя того каталога, из которого требуется получить информацию. При невозможности открыть указанный аргументом каталог функция возвращает значение NULL.

Дальнейшие действия выполняются системной функцией с прототипом

struct dirent *readdir(DIR* dirptr),

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

ino_t d_ino; /* Номер индексного дескриптора */

char d_name[ ]; /* Имя файла, заканчивающегося нулевым байтом*/

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

После окончРния использования указателя нР каталог, полученный от функции opendir(), следует выполнить закрытие доступа к каталогу и освобождение ресурсов вызовом функции с прототипом

int closedir(DIR* dirptr),

Вспомогательной функцией работы с каталогами служит описываемая прототипом

void rewinddir(DIR* dirptr),

которая позволяет вернуться к началу каталога с целью чтения его опять с самого начала.

Применение описанных функций демонстрирует программа примера, приведенного в листинге 6.8.1.

#include <unistd.h>

#include <dirent.h>

#include <string.h>

int main()

{DIR *dp;

struct dirent *de;

int len, rc;

dp=opendir(".");

if (dp= =NULL)

{printf("No those files\n"); exit(1);}

while (de=readdir(dp)) {

if (de->d_ino != 0)

{len=strlen(de->d_name);

if (!strcmp(".c",(de->d_name)+len-2))

printf("%s\n",de->d_name);

}

}

closedir(dp);

return 0;

}

Листинг 6.8.1. Программный доступ к информации каталога в Unix

Эта программа последовательно читает все записи текущего каталога (обозначаемого символом '.'), и если запись не пуста, то проверяет, не оканчивается ли имя файла, заданного в этой записи на цепочку символов ".c". При совпадении выполняется вывод имени файла на экран.

В операционных системах типа Windows и OS/2 разработчики включили проверку условия для имени файла в действия соответствующей системной функции. В этих ОС основных функций, работающих с содержимым каталогов, – две: функция поиска первого файла по задаваемому условию и функция поиска следующего файла по тому же условию. Само условие задается как метанотация, т.е. записью совокупности файлов с помощью метасимволов * и ? в соответствующем аргументе имени файла. Использование этих метасимволов полностью совпадает с традиционным их применением в командах операционной системы, восходящим к правилам командного интерпретатора Unix.

В Windows для поиска первого файла в каталоге служит функция с прототипом

HANDLE FindFirstFile(char *metaname, WIN32_FIND_DATA *FindFileData),

где аргумент metaname задает метанотацию файла в текущем каталоге или в явно заданном в аргументе каталоге, а второй аргумент задается адресом (указателем на) экземпляра структуры данных, куда должна быть помещена служебная информация о файле. Поля этой структуры данных, описывающей кроме имени файла еще и вспомогательную информацию, дают среди прочего время последней коррекции и последнего доступа (а также ряд других параметров). Наиболее значимым является поле с именем cFileName, описывающее имя файла массивом символов. При неудаче функция возвращает значение INVALID_HANDLE_VALUE (равное -1), в противном случае она возвращает специальный хэндл, предназначенный для использования только в функции продолжения поиска и закрытия этого хэндла. По существу, упомянутый хэндл соответствует хэндлу каталога, который получается от функции открытия каталога в Unix.

Для поиска следующих файлов, удовлетворяющих той же метанотации, что была задана при выполнении функции FindFirstFile, в Windows служит функция с прототипом

BOOL FindNextFile(HANDLE hFindFile, WIN32_FIND_DATA *FindFileData),

где аргумент hFindFile должен быть получен от функции FindFirstFile, а второй аргумент задает экземпляр структуры для размещения служебной информации о файле и уже рассматривался для предыдущей функции. Последняя функция возвращает значение TRUE, если находит очередной файл в текущем каталоге, удовлетворяющий метанотации, в противном случае она возвращает значение FALSE.

В завершение работы с каталогом должна вызываться функция с прототипом

BOOL FindClose(HANDLE hFindFile),

которая закрывает хэндл, ранее полученный от функции FindFirstFile.

Следующая программа для Windows, приведеная в листинге 6.8.2, демонстрирует поиск в текущем каталоге файлов, которые имеют расширение ".c", с выводом их имен на экран. По существу эта программа полностью соответствует программе в листинге 6.8.1.

#include <stdio.h>

#include <windows.h>

int main()

{HANDLE fdirsearch;

WIN32_FIND_DATA dan;

BOOL rc;

fdirsearch=FindFirstFile("*.c", &dan);

if (fdirsearch= =INVALID_HANDLE_VALUE)

{printf("No those files\n"); exit(1);}

do {

printf("%s\n",dan.cFileName);

rc=FindNextFile(fdirsearch, &dan);

} while(rc!=FALSE);

FindClose(fdirsearch);

return 0;

}

Листинг 6.8.2. Программный доступ к информации каталога в Windows

Для вспомогательных действий по переустановке текущего каталога предназначена в Windows функция с прототипом

BOOL SetCurrentDirectory(char *PathName)),

а также функция с прототипом

DWORD GetCurrentDirectory(DWORD BufferSize, char *Buffer),

которая позволяет запомнить в символьном массиве полное имя текущего каталога.