Виртуальная файловая система (VFS)
Проблема: много разных файловых систем
В одной системе одновременно работают: ext4 на системном разделе, FAT на флешке, NFS по сети, tmpfs в памяти, procfs и sysfs — вообще без диска. Каждая хранит данные по-своему. А программа просто вызывает open("/media/usb/a.txt") и read — и всё работает.
Зачем нужна VFS
Это вопрос 4(а) экзамена.
Виртуальная файловая система (VFS, Virtual File System, в System V — vnode/vfs) — слой ядра между системными вызовами и конкретными файловыми системами. Она определяет общую модель файла (объекты и их операции), а каждая ФС лишь реализует эти операции.
Что это даёт:
- Единый интерфейс для программ:
open,read,write,stat,mmapодинаково работают с любой ФС, устройствами, каналами, псевдофайлами. - Единое дерево: разные ФС монтируются в каталоги одного дерева; VFS при разборе пути переходит через точки монтирования.
- Общий код один раз: разбор путей, проверка прав, кеш элементов каталогов (dentry cache), кеш inode, кеш страниц, блокировки файлов, учёт открытых файлов.
- Расширяемость: новая ФС (даже модулем ядра) регистрируется и сразу работает со всеми программами.
- Возможность сетевых и виртуальных ФС (NFS, procfs, FUSE), у которых нет диска.
Аналогия
VFS — универсальная розетка с переходниками. Прибору (программе) всё равно, откуда электричество; каждая электростанция (ФС) подключается к сети через свой переходник (таблицу операций).
Четыре объекта VFS (Linux)
| Объект | Что описывает | Таблица операций |
|---|---|---|
суперблок (struct super_block) |
смонтированную ФС: тип, устройство, размер блока, корневой каталог, список inode, флаги монтирования | super_operations: создать/удалить/записать inode, sync_fs, statfs |
индексный дескриптор (struct inode) |
конкретный файл (объект ФС) | inode_operations: lookup, create, link, unlink, mkdir, rename, permission, setattr |
элемент каталога (struct dentry) |
компонент пути: связь «имя → inode» в каталоге-родителе; кешируется | dentry_operations |
открытый файл (struct file) |
файл, открытый процессом: позиция, режим, ссылка на dentry/inode | file_operations: read_iter, write_iter, llseek, mmap, open, release, fsync, ioctl |
В System V и BSD аналогичная пара называется vfs (смонтированная ФС) и vnode (виртуальный индексный дескриптор).
Поля виртуального индексного дескриптора
Это вопрос 4(б). Удобно разбить поля на группы.
1. Атрибуты файла (копия с диска для дисковых ФС):
| Поле Linux | Смысл |
|---|---|
i_ino |
номер inode |
i_mode |
тип файла и права |
i_uid, i_gid |
владелец и группа |
i_size, i_blocks |
размер в байтах и число блоков |
i_atime, i_mtime, i_ctime |
времена доступа, изменения данных и изменения inode |
i_nlink |
число жёстких ссылок |
i_rdev |
номер устройства (для файлов устройств) |
2. Связь с остальным ядром:
| Поле | Смысл |
|---|---|
i_sb |
указатель на суперблок — какой ФС принадлежит |
i_op |
таблица операций над inode (inode_operations) |
i_fop |
операции над файлом по умолчанию — копируются в struct file при open |
i_mapping / i_data |
address_space: кеш страниц файла и операции чтения/записи страниц |
i_dentry |
список элементов каталога (имён), ссылающихся на inode |
объединение i_pipe / i_bdev / i_cdev |
данные для каналов и устройств |
3. Служебное состояние в памяти:
| Поле | Смысл |
|---|---|
i_count |
счётчик использования в памяти (сколько dentry, file и т.д. на него ссылаются) |
i_state |
флаги: I_DIRTY (нужно записать на диск), I_NEW, I_FREEING |
i_lock, i_rwsem |
блокировки |
i_hash, i_lru, i_sb_list |
ссылки в хеш-таблице inode, списке LRU, списке суперблока |
i_flctx |
блокировки файла (flock, fcntl) |
i_private / окружающая структура |
данные конкретной ФС: ext4 встраивает struct inode в свой ext4_inode_info с адресами блоков |
Классический vnode System V содержит то же по смыслу: v_type (тип), v_count (счётчик ссылок), v_flag, v_op (указатель на vnodeops), v_vfsp (ФС, которой принадлежит), v_vfsmountedhere (ФС, смонтированная на этот каталог), v_rdev (устройство), v_pages (страницы в памяти) и v_data — указатель на «настоящий» индексный дескриптор конкретной ФС.
Как отвечать на 4(б)
Назовите три группы: (1) атрибуты файла — номер, тип и права, владелец, размер, времена, число ссылок; (2) связи — ФС (суперблок), таблица операций, кеш страниц, данные конкретной ФС; (3) состояние в памяти — счётчик использования, флаги «грязный», блокировки, ссылки в кешах. И подчеркните главное: указатель на таблицу операций делает inode «виртуальным» — VFS вызывает функции, не зная, какая это ФС.
Путь системного вызова
read(fd, buf, 100);
fd→ таблица дескрипторов процесса →struct file.- VFS вызывает
file->f_op->read_iter(...)— функцию конкретной ФС (для ext4 — обобщённое чтение через кеш страниц). - Ищутся страницы в кеше страниц файла (
inode->i_mapping). - Если нет — операции
address_spaceФС переводят смещение в номера блоков диска, блочный уровень отправляет запрос драйверу; процесс спит до завершения ввода-вывода. - Данные копируются в
buf,file->f_pos += n.
Разбор пути при open тоже делает VFS: идёт по компонентам, ищет их в кеше dentry, при промахе вызывает inode->i_op->lookup каталога, проверяет права (permission), переходит через точки монтирования.
Итог
- VFS — общий слой ядра: единый интерфейс, единое дерево, общий код и кеши, лёгкое добавление ФС.
- Объекты: суперблок (ФС), inode (файл), dentry (имя в пути), file (открытый файл с позицией); у каждого таблица операций.
- Виртуальный inode: атрибуты файла, связи (суперблок, операции, кеш страниц, данные ФС), состояние в памяти (счётчик, флаги, блокировки).
- Позиция чтения — в
struct file, а не в inode.
Практика решено 0 из 5
Для чего в ядре существует виртуальная файловая система?
Какой объект VFS описывает каждую сущность?
| Суперблок | Индексный дескриптор (inode) | Элемент каталога (dentry) | Открытый файл (file) | |
|---|---|---|---|---|
| Смонтированная файловая система целиком | ||||
| Конкретный файл: права, размер, владелец | ||||
| Компонент пути «home» в /home/anna | ||||
| Текущая позиция чтения процесса | ||||
| Размер блока ФС и список всех её inode | ||||
| Указатель на кеш страниц файла (address_space) |
Какие поля есть у виртуального индексного дескриптора (struct inode в Linux / vnode)?
Расставьте шаги выполнения read(fd, buf, 100) для файла на ext4:
- Ищутся нужные страницы в кеше страниц файла (inode->i_mapping)
- VFS вызывает file->f_op->read_iter — операцию, которую предоставила ext4
- Если страниц нет — ext4 определяет блоки диска и запрашивает чтение у блочного уровня, драйвера диска
- Данные копируются из кеша страниц в буфер пользователя, позиция в struct file увеличивается
- Системный вызов: ядро по fd находит в таблице процесса struct file
Чем inode в памяти (VFS) отличается от inode на диске?
Войдите, чтобы отмечать пройденные уроки.