Вы здесь

Виртуальная файловая система VFS

Виртуальная файловая система VFS

Для организации доступа к разнообразным файловым системам (ФС) в Unix используется промежуточный слой абстракции - виртуальная файловая система (VFS).

С точки зрения программиста VFS организована как интерфейс или абстрактный класс в объектно ориентированном языке программирования типа C++.

VFS объявляет API доступа к файловой системе, а реализацию этого API отдаёт на откуп драйверам конкретных ФС, которые можно рассматривать, как производные классы, наследующие интерфейс VFS.

Виртуальные методы VFS

Каждый драйвер ФС должен реализовать вызовы для работы с файлами, inode и с ФС в целом, описанные в заголовочном файле ядра linux/fs.h. При монтировании ФС соответствующие структуры заполняются указателями на соответствующие реализации в драйвере.

Если какая-нибудь функция отсутствует в драйвере, то указатель ссылается на функцию заглушку, которая возвращает ошибку "не реализовано" - ENOSYS.

struct file_operations {
    loff_t (*llseek) (struct file *, loff_t, int);
    ssize_t (*read) (struct file *, char *, size_t, loff_t *);
    ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
...
struct inode_operations {
    struct dentry * (*lookup) (struct inode *,struct dentry *);
    int (*create) (struct inode *,struct dentry *,int);
    int (*link) (struct dentry *,struct inode *,struct dentry *);
    int (*symlink) (struct inode *,struct dentry *,const char *);
    int (*mkdir) (struct inode *,struct dentry *,int);
...
struct super_operations {
    int (*  ) (struct super_block *, int *, char *);
    void (*umount_begin) (struct super_block *);
...

Для файловой системы ext2fs объявление соответствующих функций выглядит так:

extern struct dentry *ext2_lookup (struct inode *, struct dentry *);
extern int ext2_create (struct inode *,struct dentry *,int);
extern int ext2_mkdir (struct inode *,struct dentry *,int);
extern int ext2_rmdir (struct inode *,struct dentry *);
extern int ext2_unlink (struct inode *,struct dentry *);
...

Вызовы remount_fs() и umount_begin() можно использовать как конструктор и деструктор класса, которые вызываются в момент монтирования файловой системы и в момент размонтирования.

Виртуальный inode

Кроме виртуальных функций VFS описывает обобщённые структуры superblock, dentry (directory entry запись в каталоге),inode (в некоторых ОС называется vnode). Эти структуры содержит все основные структуры данных суперблока ФС, каталогов и inode из классической ФС Unix. Кроме того структура file содержит информацию, необходимую для работы с открытыми файлами Поскольку VFS является интерфейсом, то перечисленные структуры не содержат технических подробностей, таких как информации о размещении блоков данных файла или IP адреса сервера сетевой ФС. Для хранения деталей реализации, драйверу ФС в каждой из структур предоставляется дополнительное поле для хранения указателя на специфические для ФС структуры данных. В inode в Linux это поле выглядит так:

union {
  struct pipe_inode_info        pipe_i;
  struct minix_inode_info       minix_i;
  struct ext2_inode_info        ext2_i;
...
  void              *generic_ip;
} u;

На основе перечисленных

Драйвер ФС должен уметь конвертировать атрибуты файла, фактически хранящиеся в ФС, в поля inode. Например, драйвер NTFS должен уметь преобразовывать SID пользователя Windows в UID пользователя Unix и наоборот.

Если ФС не позволяет хранить необходимые атрибуты inode, то при монтировании драйверу можно передать некоторые дополнительные параметры, содержащие фиксированные значения для этих атрибутов. Драйвер FAT позволяет задать:

  • uid, gid - владелец и группа для всех файлов
  • dmask, fmask - маски прав доступа для файлов и каталогов, которые вычитается из rwxrwxrwx.
  • codepage, iocharset - кодовые таблицы для преобразования имён файлов на национальных алфавитов в UTF-8 или иную, используемую в Unix кодировку.
  • tz=UTC - указание, что метки времени в ФС хранятся в UTC. DOS и Windows хранят метки времени в локальном времени часового пояса.

Procfs /proc

Благодаря VFS в Unix возможно представление в виде ФС любых иерархических структур данных. Самый известный пример, это файловая система Procfs , которая отображает в виде дерева каталогов внутренние структуры ядра. Чаще всего, она смонтирована в каталог /proc, но может быть смонтирована и в другой каталог или не смонтирована вовсе.

В каталоге /proc в Linux присутствуют, по сути, два дерева ФС. В основном дереве, каждый каталог имеет числовое имя и соответствует процессу, с соответствующим PID. Файлы в этих каталогах соответствуют структурам данных, связанных с процессом. Каталог /proc/self в Linux является символической ссылкой, указывающей на каталог процесса, который к ней обратился. Например, cat /proc/self/cmdline покажет аргументы запуска cat т.е. cat /proc/self/cmdline, а ls -l /proc/self/exe покажет ссылку на исполняемый файл ls - /proc/self/exe -> /usr/bin/ls.

В дереве /proc/sys отображаются внутренние переменные ядра. Операции чтения/записи в каталоге /proc/sys позволяют настраивать такие параметры ядра как маршрутизация - /proc/sys/net/ipv4/ip_forward или максимальный объём разделяемой между процессами памяти /proc/sys/kernel/shmmax. В исторических Unix, таких как Solaris 5 такие настройки делались через отладчик, который подключался к ядру как к программе и менял значения переменных.

В последних версиях ядра Linux прослеживается тенденция вынесения доступа к новым переменным в отдельную ФС Sysfs, которая монтируется в каталог /sys.

ФС вне ядра - fuse

В Linux (а в последнее время и в Windows) есть возможность зарегистрировать в VFS свой драйвер ФС без написания кода в ядре. Адаптер fuse транслирует вызовы из ядра в обычный пользовательский процесс. Благодаря этому механизму возможно написание драйверов, написанных на любом языке программирования: C++, python, Java и т.д. Главное, написать соответствующий набор функций и через API fuse зарегистрировать их в ядре.

Известные примеры: sshfs - монтирование дисков через sftp, NTFS-3G - драйвер NTFS через fuse, различные ФС на основе баз данных.

Яндекс.Метрика