Вся указанная информация, а также связанная с ней информация о самой файловой системе хранится в суперблоке (superblock). Суперблок — это структура данных, которая содержит информацию о файловой системе в целом. Иногда эти общие данные называются метаданными файловой системы. Метаданные файловой системы содержат информацию об индивидуальных файлах и о файловой системе в целом.
Традиционно файловые системы ОС Unix реализуют эти понятия как структуры данных, которые определенным образом расположены на физических дисках. Например, информация о файлах хранится в индексе, в отдельном блоке диска, каталоги являются файлами, информация по управлению файловой системой хранится централизованно в суперблоке и т.д. Подсистема VFS операционной системы Linux рассчитана на работу с файловыми системами, в которых поддерживаются аналогичные концепции. Не Unix-подобные файловые системы, такие как FAT или NTFS, также работают в ОС Linux, однако их программный код должен обеспечить наличие аналогичных концепций. Например, если файловая система не поддерживает отдельные индексы файлов, то код должен построить в оперативной памяти структуры данных таким образом, чтобы казалось, что такая поддержка работает. Если файловая система рассматривает каталоги как объекты специальных типов, для VFS каталоги должны представляться как обычные файлы. Часто код не файловых систем не в стиле Unix требует выполнять некоторую дополнительную обработку чтобы уложиться в парадигму Unix и требования VFS. Такие файловые системы также поддерживаются, и обычно качество не особенно страдает.
Объекты VFS и их структуры данных
Виртуальная файловая система (VFS) объектно-ориентированна[69]. Общая файловая модель представлена набором структур данных. Эти структуры данных очень похожи на объекты. Так как ядро программируется строго на языке С, то, при отсутствии возможностей прямой поддержки парадигм ООП в языке программирования, структуры данных представляются структурами языка С. Структуры содержат как указатели на элементы данных, так и указатели на функции, которые работают с этими данными.
Существуют следующие четыре основных типа объектов VFS.
• Объект суперблок (superblock), который представляет определенную смонтированную файловую систему.
• Объект файловый индекс (inode), который представляет определенный файл.
• Объект элемент каталога (dentry), который представляет определенный элемент каталога.
• Объект файл (file), который представляет открытый файл, связанный с процессом.
Следует обратить внимание, что поскольку подсистема VFS рассматривает каталоги как обычные файлы, то не существует специальных объектов для каталогов. Как рассказывалось ранее, объект dentry представляет компонент пути, который может содержать обычный файл. Другими словами, dentry — это не то же самое, что каталог, а каталог — это то же, что и файл. Все понятно?
Каждый из рассмотренных основных объектов содержит объект operations (операции). Эти объекты описывают методы, которые ядро может применять для основных объектов.
В частности, существуют следующие объекты операций.
• Объект super_operations
(операции с суперблоком файловой системы) содержит методы, которые ядро может вызывать для определенной файловой системы, как, например, read_inode()
или sync_fs()
.
• Объект inode_operations
(операции с файловыми индексами) содержит методы, которые ядро может вызывать для определенного файла, как, например, create()
или link()
.
• Объект dentry_operations
(операции с элементами каталогов) содержит методы, которые ядро может вызывать для определенного элемента каталога, как, например, d_compare()
или d_delete()
.
• Объект file_operations
(операции с файлами) содержит методы, которые процесс может вызывать для открытого файла, как например, read()
и write()
.
Объекты операций реализованы в виде структур, содержащих указатели на функции. Эти функции оперируют объектом, которому принадлежит объект операций. Для многих методов объект может унаследовать общую функцию, если для работы достаточно базовой функциональности. В противном случае каждая файловая система присваивает указателям адреса своих специальных методов.
И еще раз повторимся, что под объектами мы будем понимать структуры, которые явно не являются объектными типами (в отличие от языков программирования C++ и Java). Однако эти структуры представляют определенные экземпляры объектов, данные связанные с объектами, и методы, которые ими оперируют. Это практически то же, что и объектные типы.
Другие объекты подсистемы VFS
Структуры для VFS — это самая "любимая" вещь, и в этой подсистеме существуют не только рассмотренные структуры, но и еще некоторые. Каждая зарегистрированная файловая система представлена структурой file_system_type
. Объекты этого типа описывают файловую систему и ее свойства. Более того, каждая точка монтирования представлена в виде структуры vfsmount
. Эта структура содержит информацию о точке монтирования, такую как ее положение и флаги, с которыми выполнена операция монтирования.
И наконец, каждый процесс имеет три структуры, которые описывают файловую систему и файлы, связанные с процессом. Это структуры file_struct
, fs_struct
и namespace
.
Далее в этой главе будут рассматриваться эти объекты и их роль в функционировании уровня VFS.
Объект superblock
Объект суперблок должен быть реализован для каждой файловой системы. Он используется для хранения информации, которая описывает определенную файловую систему. Этот объект обычно соответствует суперблоку (superblock) или управляющему блоку (control block) файловой системы, который хранится в специальном секторе диска (отсюда и имя объекта). Файловые системы, которые не располагаются на дисках (например, файловые системы в виртуальной памяти, как sysfs), генерируют информацию суперблока "на лету" и хранят в памяти.
Объект суперблок представляется с помощью структуры struct super_block
, которая определена в файле <linux/fs.h>
. Она выглядит следующим образом (комментарии описывают назначение каждого поля).
struct super_block {
struct list_head s_list; /* список всех суперблоков */
dev_t s_dev; /* идентификатор */
unsigned long s_blocksize; /* размер блока в байтах */
unsigned long s_old_blocksize; /* старый размер блока
в байтах */
unsigned char s_blocksize_bits; /* размер блока в битах */
unsigned char s_dirt; /* флаг того,
что суперблок изменен */
unsigned long long s_maxbytes; /* максимальный размер файла */
struct file_system_type *s_type; /* тип файловой системы */
69
Часто многие этого не замечают и даже отрицают, но тем не менее в ядре много примеров объектно-ориентированного программирования. Хотя разработчики ядра и сторонятся языка C++ и других явно объектно-ориентированных языков программировании (ООП), иногда очень полезно мыслить в терминах объектов. Подсистема VFS — это хороший пример того, как просто и эффективно объектно-ориентированное программирование реализуется на языке С, в котором нет объектно-ориентированных конструкций.