Сетевая файловая система NFS
Компания Sun Microsystems представила NFS
в 1985 году как средство обеспечения
прозрачного доступа к удаленным
файловым системам. Помимо
публикации протокола Sun
лицензировала его базовую
реализацию, которая была
использована различными
поставщиками для портирования NFS на
разные операционные системы. С тех
пор NFS стала фактически
промышленным стандартом, который
поддерживается действительно
всеми вариантами системы UNIX, а
также некоторыми другими
системами, например, VMS и MS-DOS.
Архитектура NFS базируется на
модели клиент-сервер. Файл-сервер
представляет собой машину, которая
экспортирует некоторый набор
файлов. Клиентами являются машины,
которые имеют доступ к этим файлам.
Одна машина может для различных
файловых систем выступать как в
качестве сервера, так и в качестве
клиента. Однако программный код NFS
разделен на две части, что
позволяет иметь только клиентские
или только серверные системы.
Клиенты и серверы
взаимодействуют с помощью
удаленных вызовов процедур (rpc - remote
procedure call), которые работают как
синхронные запросы. Когда
приложение на клиенте пытается
обратиться к удаленному файлу, ядро
посылает запрос в сервер, а процесс
клиента блокируется до получения
ответа. Сервер ждет приходящие
запросы, обрабатывает их и отсылает
ответы назад клиентам.
Сервер NFS экспортирует одну или
несколько файловых систем. Каждая
экспортируемая файловая система
может быть либо целым разделом
диска либо его поддеревом.
(Различные варианты UNIX имеют свои
собственные правила дробления
экспортируемых систем. Некоторые
из них могут, например, разрешать
экспортировать только файловую
систему целиком, другие - только
одно одно поддерево в каждой
файловой системе). Сервер может
определить, обычно посредством
строк в файле /etc/exports, какие клиенты
могут иметь доступ к каждой
экспортируемой файловой системе, а
также разрешенный режим доступа к
ней: "только чтение" или
"чтение и запись".
Затем клиентские машины могут
подмонтировать такую файловую
систему или ее поддерево к любому
каталогу в своей существующей
иерархии файлов, точно так же, как
они смогли бы смонтировать любую
локальную файловую систему. Клиент
может монтировать каталог с
режимом "только чтение", даже
если сервер экспортирует его в
режиме "чтение и запись". NFS
поддерживает два типа
монтирования: жесткое и мякгое. От
типа монтирования зависит
поведение клиента в случае, если
сервер не отвечает на запрос. Если
файловая система смонтирована
жестко, клиент продолжает
повторные запросы до получения
ответа. В случае мягкого
монтирования клиент спустя
некоторое время отказывается от
повторных запросов и получает
ошибку. Когда монтирование
произведено, клиент может
обращаться к файлам в удаленной
файловой системе, используя те же
самые операции, которые
применяются к локальным файлам.
Некоторые системы поддерживают
также такой тип монтирования,
поведение которого соответствует
жесткому монтированию при
организации повторных попыток
смонтировать файловую систему, но
оказывается мягким для последующих
операций ввода/вывода.
Операции монтирования NFS менее
ограничены по сравнению с
операциями монтирования локальных
файловых систем. Протокол не
требует, чтобы вызывающий операцию
монтирования пользователь был
привилегированным, хотя
большинству пользователей
навязываются эти требования.
(Например, ULTRIX компании Digital
позволяет любому пользователю
монтировать файловую систему NFS до
тех пор, пока этот пользователь
имеет права доступа по записи в
каталог точки монтирования.
Пользователь может монтировать ту
же самую файловую систему к
нескольким точкам дерева
каталогов, даже к своему
подкаталогу. Сервер может
экспортировать только свои
локальные файловые системы и не
может пересекать свои собственные
точки монтирования во время
прохода по путевому имени. Таким
образом, чтобы увидеть все файлы
сервера, клиент должен
смонтировать все его файловые
системы.
На рисунке 4.1 приведен пример.
Серверная система nfssrv имеет два
диска. Она смонтировала диск 1 к
каталогу /usr/local диска 0 и
экспортировала каталоги /usr и /usr/local.
Предположим, что клиент выполняет
следующие четыре операции mount:
mount -t nfs nfssrv:/usr /usr
mount -t nfs nfssrv:/usr/u1 /u1
mount -t nfs nfssrv:/usr /users
mount -t nfs nfssrv:/usr/local /usr/local
Рис.4.1. Монтирование
файловых систем NFS
Все четыре операции монтирования
будут успешно выполнены. На клиенте
поддерево /usr отражает полное
поддерево /usr на nfssrv, поскольку
клиент также смонтировал /usr/local.
Поддерево /u1 на клиенте отображает
поддерево /usr/u1 на nfssrv. Этот пример
иллюстрирует, что вполне законно
можно монтировать подкаталог
экспортированной файловой стстемы
(это позволяют не все реализации).
Наконец, поддерево /users на клиенте
отображает только ту часть
поддерева /usr сервера, которая
размещена на диске 0. Файловая
система диска 1 под /users/local не видна.
Первоначальная разработка NFS
имела следующие цели:
- NFS не должна ограничиваться
операционной системой UNIX.
Любая операционная система
должна быть способной
реализовать сервер и клиент NFS.
- Протокол не должен зависеть от
каких либо определенных
аппаратных средств.
- Должны быть реализованы
простые механизмы
восстановления в случае
отказов сервера или клиента.
- Приложения должны иметь
прозрачный доступ к удаленным
файлам без использования
специальных путевых имен или
библиотек и без
перекомпиляции.
- Для UNIX-клиентов должна
поддерживаться семантика UNIX.
- Производительность NFS должна
быть сравнима с
производительностью локальных
дисков.
- Реализация должна быть
независимой от транспортных
средств.
Реализация NFS состоит из
нескольких компонент. Некоторые из
них локализованы либо на сервере,
либо на клиенте, а некоторые
используются и тем и другим.
Некоторые компоненты не требуются
для обеспечения основных
функциональных возможностеей, но
составляют часть расширенного
интерфейса NFS:
- Протокол NFS определяет набор
запросов (операций), которые
могут быть направлены клиентом
к серверу, а также набор
аргументов и возвращаемые
значения для каждого из этих
запросов. Версия 1 этого
протокола существовала только
в недрах Sun Microsystems и никогда не
была выпущена. Все реализации
NFS (в том числе NFSv3) поддерживают
версию 2 NFS (NFSv2), которая впервые
была выпущена в 1985 году в SunOS 2.0.
Версия 3 протокола была
опубликована в 1993 году и
реализована некоторыми
фирмами-поставщиками. В
таблице 3.1 приведен полный
набор запросов NFS.
- Протокол удаленного вызова
процедур (RPC) определяет формат
всех взаимодействий между
клиентом и сервером. Каждый
запрос NFS посылается как пакет
RPC.
- Расширенное представление
данных (XDR - Extended Data Representation)
обеспечивает
машинно-независимый метод
кодирования данных для
пересылки через сеть. Все
запросы RPC используют
кодирование XDR для передачи
данных. Следует отметить, что XDR
и RPC используются для
реализации многих других
сервисов, помимо NFS.
- Программный код сервера NFS
отвечает за обработку всех
запросов клиента и
обеспечивает доступ к
экспортируемым файловым
системам.
- Программный код клиента NFS
реализует все обращения
клиентской системы к удаленным
файлам путем посылки серверу
одного или нескольких запросов
RPC.
- Протокол монтирования
определяет семантику
монтирования и
размонтирования файловых
систем NFS.
- NFS использует несколько
фоновых процессов-демонов. На
сервере набор демонов nfsd
ожидают запросы клиентов NFS и
отвечают на них. Демон mountd
обрабатывает запросы
монтирования. На клиенте набор
демонов biod обрабатывает
асинхронный ввод/вывод блоков
файлов NFS.
- Менеджер блокировок сети (NLM -
Network Lock Manager) и монитор
состояния сети (NSM - Network Status
Monitor) вместе обеспечивают
средства для блокировки файлов
в сети. Эти средства, хотя
формально не связаны с NFS, можно
найти в большинстве реализаций
NFS. Они обеспечивают сервисы не
возможные в базовом протоколе.
NLM и NSM реализуют
функционирование сервера с
помощью демонов lockd и statd
соответственно.
Возможно наиболее важной
характеристикой протокола NFS
является то, что сервер, чтобы
работать корректно, не запоминает
состояний и не нуждается ни в какой
информации о своих клиентах. Каждый
запрос является полностью
независимым от других запросов и
содержит всю необходимую
информацию для его обработки.
Серверу не нужно поддерживать
никаких записей о прошлых запросах
клиентов, за исключением
необязательных возможностей,
которые могут использоваться с
целью кэширования данных или для
сбора статистики.
Например, в протоколе NFS
отсутствуют запросы по открыванию
и закрыванию файлов, поскольку они
создали бы информацию о состоянии,
которая должна запоминаться
сервером. По этой же причине,
запросы read и write передают в качестве
параметра начальное смещение, в
отличие от операций read и write с
локальными файлами, которые
получают смещение из объекта
"открытый файл".
Протокол без сохранения
состояний упрощает восстановление
после краха системы. Если
отказывает клиентская система,
никакого восстановления не
требуется, поскольку сервер не
поддерживает никакой устойчивой
информации о клиенте. Если клиент
перезагрузился, он может
перемонтировать файловые системы и
запустить приложения, которые
обращаются к удаленным файлам.
Серверу не нужно ни знать, ни
беспокоиться об отказе клиента.
Если отказывает сервер, то клиент
увидит, что на свои запросы он не
получает ответы. Тогда он
продолжает повторно посылать
запросы до тех пор, пока сервер не
перезагрузится. (Это справедливо
только в случае жесткого
монтирования (которое выполняется
по умолчанию). При мягком
монтировании клиент спустя
некоторое время прекращает посылку
запросов и возвращает приложению
сообщение об ошибке). С этого
момента времени сервер начнет
получать запросы и может их
обрабатывать, поскольку запросы не
зависят ни от какой более ранней
информации о состоянии. Когда
наконец сервер ответит на запросы,
клиент перестанет их повторно
посылать. У клиента нет никаких
средств определить, действительно
ли сервер отказал и был
перезагружен, или просто медленно
выполняет операции.
Протоколы с сохранением
состояния требуют реализации
сложных механизмов восстановления
после отказа. Сервер должен
обнаруживать отказы клиента и
ликвидировать все состояния,
связанные с этим клиентом. Если
отказывает и перезагружается
сервер, он должен уведомить
клиентов так, чтобы они могли
заново создать свое состояние на
сервере.
Главная проблема работы без
сохранения состояния заключается в
том, что сервер должен
зафиксировать все изменения в
стабильной памяти до посылки
ответа на запрос. Это означает, что
не только данные файла, но и все
метаданные, такие как индексные
дескрипторы или косвенные блоки
должны быть сброшены на диск до
возвращения результатов. В
противном случае сервер может
потерять данные, о которых клиент
уверен, что они успешно записались
на диск. (Отказ системы может
привести к потере данных даже в
локальной файловой системе, но в
таких случаях пользователи знают
об отказе и о возможности потерять
данные). Работа без сохранения
состояния связана также с другими
недостатками. Она требует
отдельного протокола (NLM) для
обеспечения блокировки файлов.
Кроме того, чтобы решить проблемы
производительности операций
синхронной записи большинство
клиентов кэшируют данные и
метаданные локально. Но это
противоречит гарантиям протокола о
соблюдении согласованного
состояния.
[Предыдущая глава]
[Оглавление] [Следующая
глава]
|