Файловая система NFS. NFS: сетевая файловая система

Доброго времени, читатели и гости . Очень большой перерыв между постами был, но я снова в бою). В сегодняшней статье рассмотрю работу протокола NFS , а так же настройку сервера NFS и клиента NFS на Linux .

Введение в NFS

NFS (Network File System - сетевая файловая система ) по моему мнению - идеальное решение в локальной сети, где необходим быстрый (более быстрый по сравнению с SAMBA и менее ресурсоемкий по сравнению с удаленными файловыми системами с шифрованием - sshfs, SFTP, etc...) обмен данными и во главе угла не стоит безопасность передаваемой информации. Протокол NFS позволяет монтировать удалённые файловые системы через сеть в локальное дерево каталогов , как если бы это была примонтирована дисковая файловая система. Тем самым локальные приложения могут работать с удаленной файловой системой, как с локальной. Но нужно быть осторожным (!) с настройкой NFS , ибо при определенной конфигурации можно подвесить операционную систему клиента в ожидании бесконечного ввода/вывода. Протокол NFS основан на работе протокола RPC , который пока не поддается моему пониманию)) поэтому материал в статье будет немного расплывчат... Прежде, чем Вы сможете использовать NFS, будь это сервер или клиент, Вы должны удостовериться, что Ваше ядро имеет поддержку файловой системы NFS. Проверить поддерживает ли ядро файловую систему NFS можно, просмотрев наличие соответствующих строк в файле /proc/filesystems :

ARCHIV ~ # grep nfs /proc/filesystems nodev nfs nodev nfs4 nodev nfsd

Если указанных строк в файле /proc/filesystems не окажется, то необходимо установить описанные ниже пакеты. Это скорее всего позволит установить зависимые модули ядра для поддержки нужных файловых систем. Если после установки пакетов, поддержка NFS не будет отображена в указанном файле, то необходимо будет , с включением данной функции.

История Network File System

Протокол NFS разработан компанией Sun Microsystems и имеет в своей истории 4 версии. NFSv1 была разработана в 1989 и являлась экспериментальной, работала на протоколе UDP. Версия 1 описана в . NFSv2 была выпущена в том же 1989 г., описывалась тем же RFC1094 и так же базировалась на протоколе UDP, при этом позволяла читать не более 2Гб из файла. NFSv3 доработана в 1995 г. и описана в . Основными нововведениями третьей версии стало поддержка файлов большого размера, добавлена поддержка протокола TCP и TCP-пакетов большого размера, что существенно ускорило работоспосбоность технологии. NFSv4 доработана в 2000 г. и описана в RFC 3010, в 2003 г. пересмотрена и описана в . Четвертая версия включила в себя улучшение производительности, поддержку различных средств аутентификации (в частности, Kerberos и LIPKEY с использованием протокола RPCSEC GSS) и списков контроля доступа (как POSIX, так и Windows-типов). NFS версии v4.1 была одобрена IESG в 2010 г., и получила номер . Важным нововведением версии 4.1, является спецификация pNFS - Parallel NFS, механизма параллельного доступа NFS-клиента к данным множества распределенных NFS-серверов. Наличие такого механизма в стандарте сетевой файловой системы поможет строить распределённые «облачные» («cloud») хранилища и информационные системы.

NFS сервер

Так как у нас NFS - это сетевая файловая система, то необходимо . (Так же можно почитать статью ). Далее необходимо . В Debian это пакет nfs-kernel-server и nfs-common , в RedHat это пакет nfs-utils . А так же, необходимо разрешить запуск демона на необходимых уровнях выполнения ОС (команда в RedHat - /sbin/chkconfig nfs on , в Debian - /usr/sbin/update-rc.d nfs-kernel-server defaults ).

Установленные пакеты в Debian запускается в следующем порядке:

ARCHIV ~ # ls -la /etc/rc2.d/ | grep nfs lrwxrwxrwx 1 root root 20 Окт 18 15:02 S15nfs-common -> ../init.d/nfs-common lrwxrwxrwx 1 root root 27 Окт 22 01:23 S16nfs-kernel-server -> ../init.d/nfs-kernel-server

То есть, сначала запускается nfs-common , затем сам сервер nfs-kernel-server . В RedHat ситуация аналогичная, за тем лишь исключением, что первый скрипт называется nfslock , а сервер называется просто nfs . Про nfs-common нам сайт debian дословно говорит следующее: общие файлы для клиента и сервера NFS, этот пакет нужно устанавливать на машину, которая будет работать в качестве клиента или сервера NFS. В пакет включены программы: lockd, statd, showmount, nfsstat, gssd и idmapd . Просмотрев содержимое скрипта запуска /etc/init.d/nfs-common можно отследить следующую последовательность работы: скрипт проверяет наличие исполняемого бинарного файла /sbin/rpc.statd , проверяет наличие в файлах /etc/default/nfs-common , /etc/fstab и /etc/exports параметров, требующих запуск демонов idmapd и gssd , запускает демона /sbin/rpc.statd , далее перед запуском /usr/sbin/rpc.idmapd и /usr/sbin/rpc.gssd проверяет наличие этих исполняемых бинарных файлов, далее для демона /usr/sbin/rpc.idmapd проверяет наличие sunrpc, nfs и nfsd , а так же поддержку файловой системы rpc_pipefs в ядре (то есть наличие ее в файле /proc/filesystems ), если все удачно, то запускает /usr/sbin/rpc.idmapd . Дополнительно, для демона /usr/sbin/rpc.gssd проверяет модуль ядра rpcsec_gss_krb5 и запускает демон.

Если просмотреть содержимое скрипта запуска NFS-сервера на Debian (/etc/init.d/nfs-kernel-server ), то можно проследить следующую последовательность: при старте, скрипт проверяет существование файла /etc/exports , наличие nfsd , наличие поддержки файловой системы NFS в (то есть в файле /proc/filesystems ), если все на месте, то запускается демон /usr/sbin/rpc.nfsd , далее проверяет задан ли параметр NEED_SVCGSSD (задается в файле настроек сервера /etc/default/nfs-kernel-server ) и, если задан - запускает демона /usr/sbin/rpc.svcgssd , последним запускает демона /usr/sbin/rpc.mountd . Из данного скрипта видно, что работа сервера NFS состоит из демонов rpc.nfsd, rpc.mountd и если используется Kerberos-аутентификация, то и демон rcp.svcgssd. В краснойшляпе еще запускается демон rpc.rquotad и nfslogd (В Debian я почему-то не нашел информации об этом демоне и о причинах его отсутствия, видимо удален...).

Из этого становиться понятно, что сервер Network File System состоит из следующих процессов (читай - демонов) , расположенных в каталогах /sbin и /usr/sbin:

В NFSv4 при использовании Kerberos дополнительно запускаются демоны:

  • rpc.gssd - Демон NFSv4 обеспечивает методы аутентификации через GSS-API (Kerberos-аутентификация). Работает на клиенте и сервере.
  • rpc.svcgssd - Демон сервера NFSv4, который обеспечивает проверку подлинности клиента на стороне сервера.

portmap и протокол RPC (Sun RPC)

Кроме указанных выше пакетов, для корректной работы NFSv2 и v3 требуется дополнительный пакет portmap (в более новых дистрибутивах заменен на переименован в rpcbind ). Данный пакет обычно устанавливается автоматически с NFS как зависимый и реализует работу сервера RPС, то есть отвечает за динамическое назначение портов для некоторых служб, зарегистрированных в RPC сервере. Дословно, согласно документации - это сервер, который преобразует номера программ RPC (Remote Procedure Call) в номера портов TCP/UDP. portmap оперирует несколькими сущностями: RPC-вызовами или запросами , TCP/UDP портами , версией протокола (tcp или udp), номерами программ и версиями программ . Демон portmap запускается скриптом /etc/init.d/portmap до старта NFS-сервисов.

Коротко говоря, работа сервера RPC (Remote Procedure Call) заключается в обработке RPC-вызовов (т.н. RPC-процедур) от локальных и удаленных процессов. Используя RPC-вызовы, сервисы регистрируют или удаляют себя в/из преобразователя портов (он же отображатель портов, он же portmap, он же portmapper, он же, в новых версиях, rpcbind), а клиенты с помощью RPC-вызовов направляя запросы к portmapper получают необходимую информацию. Юзер-френдли названия сервисов программ и соответствующие им номера определены в файле /etc/rpc. Как только какой-либо сервис отправил соответствующий запрос и зарегистрировал себя на сервере RPC в отображателе портов, RPC-сервер присваивает сопоставляет сервису TCP и UDP порты на которых запустился сервис и хранит в себе ядре соответствующую информацию о работающем сервисе (о имени), уникальном номере сервиса (в соответствии с /etc/rpc) , о протоколе и порте на котором работает сервис и о версии сервиса и предоставляет указанную информацию клиентам по запросу. Сам преобразователь портов имеет номер программы (100000), номер версии - 2, TCP порт 111 и UDP порт 111. Выше, при указании состава демонов сервера NFS я указал основные RPC номера программ. Я, наверно, немного запутал Вас данным абзацем, поэтому произнесу основную фразу, которая должна внести ясность: основная функция отображателя портов заключается в том, чтобы по запросу клиента, который предоставил номер RPC-программы (или RPC-номер программы) и версию, вернуть ему (клиенту) порт, на котором работает запрошенная программа . Соответственно, если клиенту нужно обратиться к RPC с конкретным номером программы, он сначала должен войти в контакт с процессом portmap на серверной машине и определить номер порта связи с необходимым ему сервисом RPC.

Работу RPC-сервера можно представить следующими шагами:

  1. Преобразователь портов должен стартовать первым, обычно при загрузке системы. При этом создается конечная точка TCP и осуществляется открытие TCP порта 111. Также создается конечная точка UDP, которая находится в ожидании, когда на UDP порт 111 прибудет UDP датаграмма.
  2. При старте программа, работающая через сервер RPC создает конечную точку TCP и конечную точку UDP для каждой поддерживаемой версии программы. (Сервер RPC может поддерживать несколько версий. Клиент указывает требуемую версию при посылке RPC-вызова.) Динамически назначаемый номер порта закрепляется за каждой версией сервиса. Сервер регистрирует каждую программу, версию, протокол и номер порта, осуществляя соответствуюoий RPC-вызов.
  3. Когда программе клиента RPC необходимо получить необходимую информацию, она вызывает вызов процедуру преобразователя портов, чтобы получить динамически назначаемый номер порта для заданной программы, версии и протокола.
  4. В ответ на этот запрос север возвращает номер порта.
  5. Клиент отправляет сообщение RPC-запрос на номер порта, полученный в пункте 4. Если используется UDP, клиент просто посылает UDP датаграмму, содержащую сообщение RPC-вызова, на номер UDP порта, на котором работает запрошенный сервис. В ответ сервис отправляет UDP датаграмму, содержащую сообщение RPC отклика. Если используется TCP, клиент осуществляет активное открытие на номер TCP порта требуемого сервиса и затем посылает сообщение вызова RPC по установленному соединению. Сервер отвечает сообщением отклика RPC по соединению.

Для получения информации от RPC-сервера используется утилита rpcinfo . При указании параметров -p host программа выводит список всех зарегистрированных RPC программ на хосте host. Без указания хоста программа выведет сервисы на localhost. Пример:

ARCHIV ~ # rpcinfo -p прог-ма верс прото порт 100000 2 tcp 111 portmapper 100000 2 udp 111 portmapper 100024 1 udp 59451 status 100024 1 tcp 60872 status 100021 1 udp 44310 nlockmgr 100021 3 udp 44310 nlockmgr 100021 4 udp 44310 nlockmgr 100021 1 tcp 44851 nlockmgr 100021 3 tcp 44851 nlockmgr 100021 4 tcp 44851 nlockmgr 100003 2 tcp 2049 nfs 100003 3 tcp 2049 nfs 100003 4 tcp 2049 nfs 100003 2 udp 2049 nfs 100003 3 udp 2049 nfs 100003 4 udp 2049 nfs 100005 1 udp 51306 mountd 100005 1 tcp 41405 mountd 100005 2 udp 51306 mountd 100005 2 tcp 41405 mountd 100005 3 udp 51306 mountd 100005 3 tcp 41405 mountd

Как видно, rpcinfo отображает (в столбиках слева направо) номер зарегистрированной программы, версию, протокол, порт и название. С помощью rpcinfo можно удалить регистрацию программы или получить информацию об отдельном сервисе RPC (больше опций в man rpcinfo). Как видно, зарегистрированы демоны portmapper версии 2 на udp и tcp портах, rpc.statd версии 1 на udp и tcp портах, NFS lock manager версий 1,3,4, демон nfs сервера версии 2,3,4, а так же демон монтирования версий 1,2,3.

NFS сервер (точнее демон rpc.nfsd) получает запросы от клиента в виде UDP датаграмм на порт 2049. Несмотря на то, что NFS работает с преобразователем портов, что позволяет серверу использовать динамически назначаемые порты, UDP порт 2049 жестко закреплен за NFS в большинстве реализаций.

Работа протокола Network File System

Монтирование удаленной NFS

Процесс монтирования удаленной файловой системы NFS можно представить следующей схемой:

Описание протокола NFS при монтировании удаленного каталога:

  1. На сервере и клиенте запускается RPC сервер (обычно при загрузке), обслуживанием которого занимается процесс portmapper и регистрируется на порту tcp/111 и udp/111.
  2. Запускаются сервисы (rpc.nfsd,rpc.statd и др.), которые регистрируются на RPC сервере и регистрируются на произвольных сетевых портах (если в настройках сервиса не задан статичный порт).
  3. команда mount на компьютере клиента отправляет ядру запрос на монтирование сетевого каталога с указанием типа файловой системы, хоста и собственно - каталога, ядро отправляет формирует RPC-запрос процессу portmap на NFS сервере на порт udp/111 (если на клиенте не задана опция работать через tcp)
  4. Ядро сервера NFS опрашивает RPC о наличии демона rpc.mountd и возвращает ядру клиента сетевой порт, на котором работает демон.
  5. mount отправляет RPC запрос на порт, на котором работает rpc.mountd. Теперь NFS сервер может проверить достоверность клиента основываясь на его IP адресе и номере порта, чтобы убедиться, можно ли этому клиенту смонтировать указанную файловую систему.
  6. Демон монтирования возвращает описание запрошенной файловой системы.
  7. Команда mount клиента выдает системный вызов mount, чтобы связать описатель файла, полученный в шаге 5, с локальной точкой монтирования на хосте клиента. Описатель файла хранится в коде NFS клиента, и с этого момента любое обращение пользовательских процессов к файлам на файловой системе сервера будет использовать описатель файла как стартовую точку.

Обмен данными между клиентом и сервером NFS

Типичный доступ к удаленной файловой системе можно описать следующей схемой:

Описание процесса обращения к файлу, расположенному на сервере NFS:

  1. Клиенту (пользовательскому процессу) безразлично, получает ли он доступ к локальному файлу или к NFS файлу. Ядро занимается взаимодействием с железом через модули ядра или встроенные системные вызовы.
  2. Модуль ядра kernel/fs/nfs/nfs.ko, который выполняет функции NFS клиента отправляет RPC запросы NFS серверу через модуль TCP/IP. NFS обычно использует UDP, однако более новые реализации могут использовать TCP.
  3. NFS сервер получает запросы от клиента в виде UDP датаграмм на порт 2049. Несмотря на то, что NFS может работать с преобразователем портов, что позволяет серверу использовать динамически назначаемые порты, UDP порт 2049 жестко закреплен за NFS в большинстве реализаций.
  4. Когда NFS сервер получает запрос от клиента, он передаётся локальной подпрограмме доступа к файлу, которая обеспечивает доступ к локальному диску на сервере.
  5. Результат обращения диску возвращается клиенту.

Настройка сервера NFS

Настройка сервера в целом заключается в задании локальных каталогов, разрешенных для монтирования удаленными системами в файле /etc/exports . Это действие называется экспорт иерархии каталогов . Основными источниками информации об экспортированных каталогах служат следующие файлы:

  • /etc/exports - основной конфигурационный файл, хранящий в себе конфигурацию экспортированных каталогов. Используется при запуске NFS и утилитой exportfs.
  • /var/lib/nfs/xtab - содержит список каталогов, монтированных удаленными клиентами. Используется демоном rpc.mountd, когда клиент пытается смонтировать иерархию (создается запись о монтировании).
  • /var/lib/nfs/etab - список каталогов, которые могут быть смонтированы удаленными системами с указанием всех параметров экспортированных каталогов.
  • /var/lib/nfs/rmtab - список каталогов, которые не разэкспортированы в данный момент.
  • /proc/fs/nfsd - специальная файловая система (ядро 2.6) для управления NFS сервером.
    • exports - список активных экспортированных иерархий и клиентов, которым их экспортировали, а также параметры. Ядро получает данную информацию из /var/lib/nfs/xtab.
    • threads - содержит число потоков (также можно изменять)
    • с помощью filehandle можно получить указатель на файл
    • и др...
  • /proc/net/rpc - содержит "сырую" (raw) статистику, которую можно получить с помощью nfsstat, а также различные кеши.
  • /var/run/portmap_mapping - информация о зарегистрированных в RPC сервисах

Прим: вообще, в интернете куча трактовок и формулировок назначения файлов xtab, etab, rmtab, кому верить - не знаю Даже на http://nfs.sourceforge.net/ трактовка не однозначна.

Настройка файла /etc/exports

В простейшем случае, файл /etc/exports является единственным файлом, требующим редактирования для настройки NFS-сервера. Данный файл управляет следующими аспектами:

  • Какие клиенты могут обращаться к файлам на сервере
  • К каким иерархиям каталогов на сервере может обращаться каждый клиент
  • Как пользовательские имена клиентов будут отображаться на локальные имена пользователей

Каждая строка файла exports имеет следующий формат:

точка_экспорта клиент1 (опции ) [клиент2(опции) ...]

Где точка_экспорта абсолютный путь экспортируемой иерархии каталогов, клиент1 - n имя одного или более клиентов или IP-адресов, разделенные пробелами, которым разрешено монтировать точку_экспорта . Опции описывают правила монтирования для клиента , указанного перед опциями .

Вот типичный пример конфигурации файла exports:

ARCHIV ~ # cat /etc/exports /archiv1 files(rw,sync) 10.0.0.1(ro,sync) 10.0.230.1/24(ro,sync)

В данном примере компьютерам files и 10.0.0.1 разрешен доступ к точке экспорта /archiv1, при этом, хосту files на чтение/запись, а для хоста 10.0.0.1 и подсети 10.0.230.1/24 доступ только на чтение.

Описания хостов в /etc/exports допускается в следующем формате:

  • Имена отдельных узлов описываются, как files или files.DOMAIN.local.
  • Описание маски доменов производится в следующем формате: *DOMAIN.local включает все узлы домена DOMAIN.local.
  • Подсети задаются в виде пар адрес IP/маска. Например: 10.0.0.0/255.255.255.0 включает все узлы, адреса которых начинаются с 10.0.0.
  • Задание имени сетевой группы @myclients имеющей доступ к ресурсу (при использовании сервера NIS)

Общие опции экспорта иерархий каталогов

В файле exports используются следующие общие опции (сначала указаны опции применяемые по-умолчанию в большинстве систем, в скобках - не по-умолчанию):

  • auth_nlm (no_auth_nlm) или secure_locks (insecure_locks) - указывает, что сервер должен требовать аутентификацию запросов на блокировку (с помощью протокола NFS Lock Manager (диспетчер блокировок NFS)).
  • nohide (hide) - если сервер экспортирует две иерархии каталогов, при этом одна вложенна (примонтированна) в другую. Клиенту необходимо явно смонтировать вторую (дочернюю) иерархию, иначе точка монтирования дочерней иерархии будет выглядеть как пустой каталог. Опция nohide приводит к появлению второй иерархии каталогов без явного монтирования. (прим: я данную опцию так и не смог заставить работать...)
  • ro (rw) - Разрешает только запросы на чтение (запись). (в конечном счете - возможно прочитать/записать или нет определяется на основании прав файловой системы, при этом сервер не способен отличить запрос на чтение файла от запроса на исполнение, поэтому разрешает чтение, если у пользователя есть права на чтение или исполнение.)
  • secure (insecure) - требует, чтобы запросы NFS поступали с защищенных портов (< 1024), чтобы программа без прав root не могла монтировать иерархию каталогов.
  • subtree_check (no_subtree_check) - Если экспортируется подкаталог фаловой системы, но не вся файловая система, сервер проверяет, находится ли запрошенный файл в экспортированном подкаталоге. Отключение проверки уменьшает безопасность, но увеличивает скорость передачи данных.
  • sync (async) - указывает, что сервер должен отвечать на запросы только после записи на диск изменений, выполненных этими запросами. Опция async указывает серверу не ждать записи информации на диск, что повышает производительность, но понижает надежность, т.к. в случае обрыва соединения или отказа оборудования возможна потеря информации.
  • wdelay (no_wdelay) - указывает серверу задерживать выполнение запросов на запись, если ожидается последующий запрос на запись, записывая данные более большими блоками. Это повышает производительность при отправке больших очередей команд на запись. no_wdelay указывает не откладывать выполнение команды на запись, что может быть полезно, если сервер получает большое количество команд не связанных друг с другом.

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

Файл устройства относится к интерфейсу . При экспорте файла устройства экспортируется этот интерфейс. Если клиентская система не имеет устройства такого же типа, то экспортированное устройство не будет работать. В клиентской системе, при монтировании NFS объектов можно использовать опцию nodev, чтобы файлы устройств в монтируемых каталогах не использовались.

Опции по умолчанию в разных системах могут различаться, их можно посмотреть в файле /var/lib/nfs/etab. После описания экспортированного каталога в /etc/exports и перезапуска сервера NFS все недостающие опции (читай: опции по-умолчанию) будут отражены в файле /var/lib/nfs/etab.

Опции отображения (соответствия) идентификаторов пользователей

Для большего понимания нижесказанного я бы посоветовал ознакомиться со статьей . Каждый пользователь Linux имеет свои UID и главный GID, которые описаны в файлах /etc/passwd и /etc/group . Сервер NFS считает, что операционная система удаленного узла выполнила проверку подлинности пользователей и назначила им корректные идентификаторы UID и GID. Экспортирование файлов дает пользователям системы клиента такой же доступ к этим файлам, как если бы они регистрировались напрямую на сервере. Соответственно, когда клиент NFS посылает запрос серверу, сервер использует UID и GID для идентификации пользователя в локальной системе, что может приводить к некоторым проблемам:

  • пользователь может не иметь одни и те же идентификаторы в обеих системах и, соответственно, может получить доступ к фалам другого пользователя.
  • т.к. у пользователя root идентификатор всегда 0, то данный пользователь отображается на локального пользователя в зависимости от заданных опций.

Следующие опции задают правила отображения удаленных пользователей в локальных:

  • root_squash (no_root_squash) - При заданной опции root_squash , запросы от пользователя root отображаются на анонимного uid/gid, либо на пользователя, заданного в параметре anonuid/anongid.
  • no_all_squash (all_squash) - Не изменяет UID/GID подключающегося пользователя. Опция all_squash задает отображение ВСЕХ пользователей (не только root), как анонимных или заданных в параметре anonuid/anongid.
  • anonuid=UID и anongid=GID - Явно задает UID/GID для анонимного пользователя.
  • map_static=/etc/file_maps_users - Задает файл, в котором можно задать сопоставление удаленных UID/GID - локальным UID/GID.

Пример использования файла маппинга пользователей:

ARCHIV ~ # cat /etc/file_maps_users # Маппинг пользователей # remote local comment uid 0-50 1002 # сопоставление пользователей с удаленным UID 0-50 к локальному UID 1002 gid 0-50 1002 # сопоставление пользователей с/span удаленным GID 0-50 к локальному GID 1002

Управление сервером NFS

Управление сервером NFS осуществляется с помощью следующих утилит:

  • nfsstat
  • showmsecure (insecure)ount

nfsstat: статистика NFS и RPC

Утилита nfsstat позволяет посмотреть статистику RPC и NFS серверов. Опции команды можно посмотреть в man nfsstat .

showmount: вывод информации о состоянии NFS

Утилита showmount запрашивает демон rpc.mountd на удалённом хосте о смонтированных файловых системах. По умолчанию выдаётся отсортированный список клиентов. Ключи:

  • --all - выдаётся список клиентов и точек монтирования с указанием куда клиент примонтировал каталог. Эта информация может быть не надежной.
  • --directories - выдаётся список точек монтирования
  • --exports - выдаётся список экспортируемых файловых систем с точки зрения nfsd

При запуске showmount без аргументов, на консоль будет выведена информация о системах, которым разрешено монтировать локальные каталоги. Например, хост ARCHIV нам предоставляет список экспортированных каталогов с IP адресами хостов, которым разрешено монтировать указанные каталоги:

FILES ~ # showmount --exports archiv Export list for archiv: /archiv-big 10.0.0.2 /archiv-small 10.0.0.2

Если указать в аргументе имя хоста/IP, то будет выведена информация о данном хосте:

ARCHIV ~ # showmount files clnt_create: RPC: Program not registered # данное сообщение говорит нам, что на хосте FILES демон NFSd не запущен

exportfs: управление экспортированными каталогами

Данная команда обслуживает экспортированные каталоги, заданные в файле /etc/exports , точнее будет написать не обслуживает, а синхронизирует с файлом /var/lib/nfs/xtab и удаляет из xtab несуществующие. exportfs выполняется при запуске демона nfsd с аргументом -r. Утилита exportfs в режиме ядра 2.6 общается с демоном rpc.mountd через файлы каталога /var/lib/nfs/ и не общается с ядром напрямую. Без параметров выдаёт список текущих экспортируемых файловых систем.

Параметры exportfs:

  • [клиент:имя-каталога] - добавить или удалить указанную файловую систему для указанного клиента)
  • -v - выводить больше информации
  • -r - переэкспортировать все каталоги (синхронизировать /etc/exports и /var/lib/nfs/xtab)
  • -u - удалить из списка экспортируемых
  • -a - добавить или удалить все файловые системы
  • -o - опции через запятую (аналогичен опциям применяемым в /etc/exports; т.о. можно изменять опции уже смонтированных файловых систем)
  • -i - не использовать /etc/exports при добавлении, только параметры текущей командной строки
  • -f - сбросить список экспортируемых систем в ядре 2.6;

Клиент NFS

Прежде чем обратиться к файлу на удалённой файловой системе клиент (ОС клиента) должен смонтировать её и получить от сервера указатель на неё . Монтирование NFS может производиться с помощью или с помощью одного из расплодившихся автоматических монтировщиков (amd, autofs, automount, supermount, superpupermount). Процесс монтирования хорошо продемонстрирована выше на иллюстрации.

На клиентах NFS никаких демонов запускать не нужно, функции клиента выполняет модуль ядра kernel/fs/nfs/nfs.ko , который используется при монтировании удаленной файловой системы. Экспортированные каталоги с сервера могут монтироваться на клиенте следующими способами:

  • вручную, с помощью команды mount
  • автоматически при загрузке, при монтировании файловых систем, описанных в /etc/fstab
  • автоматически с помощью демона autofs

Третий способ с autofs в данной статье я рассматривать не буду, ввиду его объемной информации. Возможно в следующих статьях будет отдельное описание.

Монтирование файловой системы Network Files System командой mount

Пример использования команды mount представлен в посте . Тут я рассмотрю пример команды mount для монтирования файловой системы NFS:

FILES ~ # mount -t nfs archiv:/archiv-small /archivs/archiv-small FILES ~ # mount -t nfs -o ro archiv:/archiv-big /archivs/archiv-big FILES ~ # mount ....... archiv:/archiv-small on /archivs/archiv-small type nfs (rw,addr=10.0.0.6) archiv:/archiv-big on /archivs/archiv-big type nfs (ro,addr=10.0.0.6)

Первая команда монтирует экспортированный каталог /archiv-small на сервере archiv в локальную точку монтирования /archivs/archiv-small с опциями по умолчанию (то есть для чтения и записи). Хотя команда mount в последних дистрибутивах умеет понимать какой тип файловой системы используется и без указания типа, все же указывать параметр -t nfs желательно. Вторая команда монтирует экспортированный каталог /archiv-big на сервере archiv в локальный каталог /archivs/archiv-big с опцией только для чтения (ro ). Команда mount без параметров наглядно отображает нам результат монтирования. Кроме опции только чтения (ro), возможно задать другие основные опции при монтировании NFS :

  • nosuid - Данная опция запрещает исполнять программы из смонтированного каталога.
  • nodev (no device - не устройство) - Данная опция запрещает использовать в качестве устройств символьные и блочные специальные файлы.
  • lock (nolock) - Разрешает блокировку NFS (по умолчанию). nolock отключает блокировку NFS (не запускает демон lockd) и удобна при работе со старыми серверами, не поддерживающими блокировку NFS.
  • mounthost=имя - Имя хоста, на котором запущен демон монтирования NFS - mountd.
  • mountport=n - Порт, используемый демоном mountd.
  • port=n - порт, используемый для подключения к NFS серверу (по умолчанию 2049, если демон rpc.nfsd не зарегистрирован на RPC-сервере). Если n=0 (по умолчанию), то NFS посылает запрос к portmap на сервере, чтобы определить порт.
  • rsize=n (read block size - размер блока чтения) - Количество байтов, читаемых за один раз с NFS-сервера. Стандартно - 4096.
  • wsize=n (write block size - размер блока записи) - Количество байтов, записываемых за один раз на NFS-сервер. Стандартно - 4096.
  • tcp или udp - Для монтирования NFS использовать протокол TCP или UDP соответственно.
  • bg - При потери доступа к серверу, повторять попытки в фоновом режиме, чтобы не блокировать процесс загрузки системы.
  • fg - При потери доступа к серверу, повторять попытки в приоритетном режиме. Данный параметр может заблокировать процесс загрузки системы повторениями попыток монтирования. По этой причине параметр fg используется преимущественно при отладке.

Опции, влияющие на кэширование атрибутов при монтировании NFS

Атрибуты файлов , хранящиеся в (индексных дескрипторах), такие как время модификации, размер, жесткие ссылки, владелец, обычно изменяются не часто для обычных файлов и еще реже - для каталогов. Многи программы, например ls, обращаются к файлам только для чтения и не меняют атрибуты файлов или содержимое, но затрачивают ресурсы системы на дорогостоящие сетевые операции. Чтобы избежать ненужных затрат ресурсов, можно кэшировать данные атрибуты . Ядро использует время модификации файла, чтобы определить устарел ли кэш, сравнивая время модификации в кэше и время модификации самого файла. Кэш атрибутов периодически обновляется в соответствии с заданными параметрами:

  • ac (noac) (attrebute cache - кэширование атрибутов) - Разрешает кэширование атрибутов (по-умолчанию). Хотя опция noac замедляет работу сервера, она позволяет избежать устаревания атрибутов, когда несколько клиентов активно записывают информацию в общию иерархию.
  • acdirmax=n (attribute cache directory file maximum - кэширование атрибута максимум для файла каталога) - Максимальное количество секунд, которое NFS ожидает до обновления атрибутов каталога (по-умолчанию 60 сек.)
  • acdirmin=n (attribute cache directory file minimum - кэширование атрибута минимум для файла каталога) - Минимальное количество секунд, которое NFS ожидает до обновления атрибутов каталога (по-умолчанию 30 сек.)
  • acregmax=n (attribute cache regular file maximum - кэширование атрибута максимум для обычного файла) - Максимаьное количество секунд, которое NFS ожидает до обновления атрибутов обычного файла (по-умолчанию 60 сек.)
  • acregmin=n (attribute cache regular file minimum - кэширование атрибута минимум для обычного файла) - Минимальное количество секунд, которое NFS ожидает до обновления атрибутов обычного файла (по-умолчанию 3 сек.)
  • actimeo=n (attribute cache timeout - таймаут кэширования атрибутов) - Заменяет значения для всех вышуказаных опций. Если actimeo не задан, то вышеуказанные значения принимают значения по умолчанию.

Опции обработки ошибок NFS

Следующие опции управляют действиями NFS при отсутствии ответа от сервера или в случае возникновения ошибок ввода/вывода:

  • fg (bg) (foreground - передний план, background - задний план) - Производить попытки монтирования отказавшей NFS на переднем плане/в фоне.
  • hard (soft) - выводит на консоль сообщение "server not responding" при достижении таймаута и продолжает попытки монтирования. При заданной опции soft - при таймауте сообщает вызвавшей операцию программе об ошибке ввода/вывода. (опцию soft советуют не использовать)
  • nointr (intr) (no interrupt - не прерывать) - Не разрешает сигналам прерывать файловые операции в жестко смонтированной иерархии каталогов при достижении большого таймаута. intr - разрешает прерывание.
  • retrans=n (retransmission value - значение повторной передачи) - После n малых таймаутов NFS генерирует большой таймаут (по-умолчанию 3). Большой таймаут прекращает выполнение операций или выводит на консоль сообщение "server not responding", в зависимости от указания опции hard/soft.
  • retry=n (retry value - значение повторно попытки) - Количество минут повторений службы NFS операций монтирования, прежде чем сдаться (по-умолчанию 10000).
  • timeo=n (timeout value - значение таймаута) - Количество десятых долей секунды ожидания службой NFS до повторной передачи в случае RPC или малого таймаута (по-умолчанию 7). Это значение увеличивается при каждом таймауте до максимального значения 60 секунд или до наступления большого таймаута. В случае занятой сети, медленного сервера или при прохождении запроса через несколько маршрутизаторов или шлюзов увеличение этого значения может повысить производительность.

Автоматическое монтирование NFS при загрузке (описание файловых систем в /etc/fstab)

Подобрать оптимальный timeo для определенного значения передаваемого пакета (значений rsize/wsize), можно с помощью команды ping:

FILES ~ # ping -s 32768 archiv PING archiv.DOMAIN.local (10.0.0.6) 32768(32796) bytes of data. 32776 bytes from archiv.domain.local (10.0.0.6): icmp_req=1 ttl=64 time=0.931 ms 32776 bytes from archiv.domain.local (10.0.0.6): icmp_req=2 ttl=64 time=0.958 ms 32776 bytes from archiv.domain.local (10.0.0.6): icmp_req=3 ttl=64 time=1.03 ms 32776 bytes from archiv.domain.local (10.0.0.6): icmp_req=4 ttl=64 time=1.00 ms 32776 bytes from archiv.domain.local (10.0.0.6): icmp_req=5 ttl=64 time=1.08 ms ^C --- archiv.DOMAIN.local ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4006ms rtt min/avg/max/mdev = 0.931/1.002/1.083/0.061 ms

Как видно, при отправке пакета размером 32768 (32Kb) время его путешествия от клиента до сервера и обратно плавает в районе 1 миллисекунды. Если данное время будет зашкаливать за 200 мс, то стоит задуматься о повышении значения timeo, чтобы оно превышало значение обмена в три-четыре раза. Соответственно, данный тест желательно делать во время сильной загрузки сети

Запуск NFS и настройка Firewall

Заметка скопипсчена с блога http://bog.pp.ru/work/NFS.html, за что ему огромное спасибо!!!

Запуск сервера NFS, монтирования, блокировки, квотирования и статуса с "правильными" портами (для сетевого экрана)

  • желательно предварительно размонтировать все ресурсы на клиентах
  • остановить и запретить запуск rpcidmapd, если не планируется использование NFSv4: chkconfig --level 345 rpcidmapd off service rpcidmapd stop
  • если нужно, то разрешить запуск сервисов portmap, nfs и nfslock: chkconfig --levels 345 portmap/rpcbind on chkconfig --levels 345 nfs on chkconfig --levels 345 nfslock on
  • если нужно, то остановить сервисы nfslock и nfs, запустить portmap/rpcbind, выгрузить модули service nfslock stop service nfs stop service portmap start # service rpcbind start umount /proc/fs/nfsd service rpcidmapd stop rmmod nfsd service autofs stop # где-то потом его надо запустить rmmod nfs rmmod nfs_acl rmmod lockd
  • открыть порты в
    • для RPC: UDP/111, TCP/111
    • для NFS: UDP/2049, TCP/2049
    • для rpc.statd: UDP/4000, TCP/4000
    • для lockd: UDP/4001, TCP/4001
    • для mountd: UDP/4002, TCP/4002
    • для rpc.rquota: UDP/4003, TCP/4003
  • для сервера rpc.nfsd добавить в /etc/sysconfig/nfs строку RPCNFSDARGS="--port 2049"
  • для сервера монтирования добавить в /etc/sysconfig/nfs строку MOUNTD_PORT=4002
  • для настройки rpc.rquota для новых версий необходимо добавить в /etc/sysconfig/nfs строку RQUOTAD_PORT=4003
  • для настройки rpc.rquota необходимо для старых версий (тем не менее, надо иметь пакет quota 3.08 или свежее) добавить в /etc/services rquotad 4003/tcp rquotad 4003/udp
  • проверит адекватность /etc/exports
  • запустить сервисы rpc.nfsd, mountd и rpc.rquota (заодно запускаются rpcsvcgssd и rpc.idmapd, если не забыли их удалить) service nfsd start или в новых версиях service nfs start
  • для сервера блокировки для новых систем добавить в /etc/sysconfig/nfs строки LOCKD_TCPPORT=4001 LOCKD_UDPPORT=4001
  • для сервера блокировки для старых систем добавить непосредственно в /etc/modprobe[.conf]: options lockd nlm_udpport=4001 nlm_tcpport=4001
  • привязать сервер статуса rpc.statd к порту 4000 (для старых систем в /etc/init.d/nfslock запускать rpc.statd с ключом -p 4000) STATD_PORT=4000
  • запустить сервисы lockd и rpc.statd service nfslock start
  • убедиться, что все порты привязались нормально с помощью "lsof -i -n -P" и "netstat -a -n" (часть портов используется модулями ядра, которые lsof не видит)
  • если перед "перестройкой" сервером пользовались клиенты и их не удалось размонтировать, то придётся перезапустить на клиентах сервисы автоматического монтирования (am-utils , autofs)

Пример конфигурации NFS сервера и клиента

Конфигурация сервера

Если вы хотите сделать ваш разделённый NFS каталог открытым и с правом записи, вы можете использовать опцию all_squash в комбинации с опциями anonuid и anongid . Например, чтобы установить права для пользователя "nobody" в группе "nobody", вы можете сделать следующее:

ARCHIV ~ # cat /etc/exports # Доступ на чтение и запись для клиента на 192.168.0.100, с доступом rw для пользователя 99 с gid 99 /files 192.168.0.100(rw,sync,all_squash,anonuid=99,anongid=99)) # Доступ на чтение и запись для клиента на 192.168.0.100, с доступом rw для пользователя 99 с gid 99 /files 192.168.0.100(rw,sync,all_squash,anonuid=99,anongid=99))

Это также означает, что если вы хотите разрешить доступ к указанной директории, nobody.nobody должен быть владельцем разделённой директории:

man mount
man exports
http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.prftungd/doc/prftungd/nfs_perf.htm - производительность NFS от IBM.

С Уважением, Mc.Sim!

ФЕДЕРАЛЬНОЕ АГЕНТСТВО ВОЗДУШНОГО ТРАНСПОРТА

ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ

ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ

«МОСКОВСКИЙ ГОСУДАРСТВЕННЫЙ

ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ

ГРАЖДАНСКОЙ АВИАЦИИ»

____________________________________________________________________________________________________________________

Кафедра вычислительных машин, комплексов, систем и сетей

СЕТЕВЫЕ ОПЕРАЦИОННЫЕ СИСТЕМЫ.

СЕТЕВЫЕ ФАЙЛОВЫЕ СИСТЕМЫ

И СЛУЖБА КАТАЛОГОВ

Утверждено Редакционно-

издательским Советом МГТУ ГА

Москва - 2010

ББК 32.973.202-018.2я73-1+32.973.26-018.2я73-1

Печатается по решению редакционно-издательского совета

Московского государственного технического университета ГА

Рецензенты: канд. физ.-мат. наук, доц. ;

Ч48 Сетевые операционные системы. Сетевые файловые системы и служба каталогов: Учебное пособие. - М.: МГТУ ГА, 2010. –68 с. 10 ил., лит.: 4 наим.

Данное учебное пособие издается в соответствии с рабочей программой учебной дисциплины «Сетевые операционные системы» по Учебному плану специальности 230101 для студентов IV курса дневного обучения.

Рассмотрено и одобрено на заседаниях кафедры 11.05.10 г. и методического совета 14.05.10 г.

-038 ББК 32.973.202-018.2я73-1+32.973.26-018.2я73-1

Ц33(03)-10 Св. тем. план 2010 г.

ЧЕРКАСОВА Наталья Ивановна

СЕТЕВЫЕ ОПЕРАЦИОННЫЕ СИСТЕМЫ.
СЕТЕВЫЕ ФАЙЛОВЫЕ СИСТЕМЫ И СЛУЖБА КАТАЛОГОВ
Учебное пособие

Редактор

Подписано в печать 11.10.10 г.

Печать офсетная Формат 60х84/16 4,0 уч.-изд. л.

3,95 усл. печ. л. Заказ № 000/ Тираж 100 экз.

Московский государственный технический университет ГА

125993 Москва, Кронштадтский бульвар, д. 20

Редакционно-издательский отдел

125493 Москва, ул. Пулковская, д.6а

© Московский государственный

технический университет ГА, 2010

Раздел 1. Состав сетевых операционных систем

1.1. Сетевые ОС. Определение, основные свойства

Сеть (Network) может быть какой угодно, начиная от простого набора компьютеров (два связанных компьютера уже есть сеть) до глобальной сети Internet , использующей множество разнообразных средств связи, включая микроволновые и спутниковые технологии.

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

Рассматриваются две разновидности сетей: LAN (Local area network) – локальная сеть, набор компьютеров и устройств, объединенных в пределах одного здания, и WAN(Wide area network) – глобальная сеть совмещает в себе несколько географически разделенных локальных сетей, которые связаны посредством различных WAN - технологий.

Назначение сети зависит от потребностей человека или организации, но, в общем случае, можно перечислить следующие возможности использования сетей:

1) совместное использование файлов. Сеть позволяет использовать файлы данных как хранящиеся в компьютере конкретного пользователя, так и файлы, размещенные на специализированном файловом сервере;

2) совместное использование аппаратных средств;

3) совместное использование программного обеспечения ;

4) обмен информацией между пользователями;

5) сетевые игры.

Сеть представляет в пользование не только локальные ресурсы, но само наличие сети означает, что ее можно объединить с другими сетями.

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

Распределенные ОС, динамически и автоматически распределяя работы по различным машинам системы для обработки, заставляют работать набор сетевых машин как виртуальный унипроцессор. Распределенная ОС работает как единая операционная система в масштабах вычислительной системы.

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

Термин сетевая ОС используется в двух значениях: во-первых, как совокупность ОС всех компьютеров сети, во-вторых, как ОС отдельного компьютера, способного работать в сети. Функционально сетевую ОС можно разделить на следующие компоненты:

1) средства управления локальными ресурсами, то есть все функции ОС автономного компьютера;

2) серверная часть ОС – средство предоставления локальных ресурсов и услуг в общее пользование;

3) клиентская часть ОС – средства доступа к удаленным ресурсам и услугам;

4) транспортные средства ОС, которые совместно с коммуникационной системой обеспечивают передачу сообщений между компьютерами сети.

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

Сетевые службы являются клиент – серверными системами, то есть содержит в своем составе клиентскую и серверную часть. Однако сетевая служба может быть представлена в ОС либо обеими частями, либо только одной из них.

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

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

Глубина внедрения сетевых служб в ОС определяет несколько подходов к построению сетевых ОС:

1) сетевые службы объединены в виде некоторого набора – оболочки;

2) сетевые службы поставляются и производятся в виде отдельного продукта;

3) сетевые службы внедрены в ОС.

Различные цели, преследуемые при создании различных сетей, предполагают наличие различных типов сетей. Одноранговая сеть (Peer-to-Peer Network) представляет собой простой способ объединения персональных компьютеров в тех случаях, когда необходимо совместное использование файлов и прочих ресурсов. В одноранговой сети нет сервера, и все компьютеры функционируют как равноправные узлы. Одноранговую сеть часто называют рабочей группой (Workgroup), так как этот термин ассоциируется с равноправным сотрудничеством без централизованного управления.

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

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

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

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

ОС DOS не поддерживала одноранговые сети, поэтому для совместного использования файлов или принтеров требовались дополнительные программные продукты, т. е. сетевые функции реализовывались сетевыми оболочками, работающими поверх ОС. Для поддержки рабочих групп использовались такие программные продукты, как Artisoft LANtastic, Novell NetWare Lite, Personal NetWare и Windows for Workgroup 3.11. Все последующие версии Windows поддерживают рабочие группы.

Дистрибутивы Linux также поддерживают создание рабочих групп из компьютеров, работающих под управлением Windows или Linux с помощью программы Samba.

Хотя к основным достоинствам одноранговых сетей относится, прежде всего, простота установки, имеется и ряд других преимуществ:

1) обычно все необходимое обеспечение уже включено в состав ОС;

2) не требуется системное администрирование, и отдельные пользователи сами могут управлять ресурсами;

3) узлы сети не зависят от сервера, следовательно, они могут работать даже тогда, когда другие узлы недоступны.

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

Сети с выделенным сервером (или серверами) (Server – based network) могут быть очень крупными и предоставлять пользователям более широкий диапазон ресурсов по сравнению с одноранговыми сетями. Связано это, прежде всего, с тем, что в такой сети имеются различные специализированные серверы.

Кроме того, эти сети позволяют осуществлять централизованное управление ресурсами и добавлять в сеть новые компьютеры, пользователей и ресурсы. Такие сети являются масштабируемыми, то есть могут легко расширяться.

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

Как и у одноранговой сети, сети с выделенным сервером имеют свои достоинства и недостатки. Прежде всего, перечислим достоинства:

1) для получения доступа к сетевым ресурсам пользователь вводит только одно регистрационное имя и пароль;

2) управление безопасностью в сети и сетевыми ресурсами осуществляется централизованно;

3) централизованное размещение позволяет выполнять резервное копирование каталогов и файлов;

4) специализированные серверы обеспечивают быстрый доступ к ресурсам;

5) подобные сети можно расширять.

Теперь отметим ряд недостатков:

1) необходимо осуществлять настройку и управление ресурсами в сети, то есть необходим системный администратор;

2) при сбое главного сервера доступ к сетевым ресурсам прекращается;

3) экономически сети с выделенным сервером выгодны только для достаточно крупных компаний.

Таким образом, в зависимости от того, как распределены функции между компьютерами сети, они могут выступать в трех различных ролях:

1) компьютер в роли выделенного сервера сети, то есть только обслуживающий запросы других компьютеров;

2) компьютер, обращающийся с запросом к ресурсам другой машины, - клиентский узел;

3) компьютер, совмещающий функции клиента и сервера, - одноранговый узел.

Следовательно, можно определить различные схемы построения сети, как:

1) одноранговая сеть – сеть на основе одноранговых узлов;

2) сеть с выделенным сервером – сеть на основе клиентов и серверов.

Однако сеть может включать в себя узлы всех типов – гибридная сеть, которую иногда относят к сетям с выделенным сервером.

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

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

Разработчики NetWare для оптимизации выполнения сервисных услуг полностью исключили из системы многие элементы универсальной ОС, оставив исключительно сетевые. Однако многие компании, разрабатывающие сетевые ОС, выпускают два варианта операционных систем, основанных на одном базовом коде, но отличающемся набором служб и утилит, - серверные и клиентские ОС.

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

Рассмотрим основные специализированные серверы.

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

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

Некоторые типы серверов используются не для получения доступа к ресурсам, а для повышения качества и эффективности работы в сети. Например, DNS - сервер (Domaine Name Service) – служба имен доменов выполняет преобразование дружественных имен в соответствующие адреса.

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

Этот процесс осуществляется компонентом клиентского программного обеспечения, который называют редиректор (REDIRECTOR). Он перехватывает любые запросы, выполненные на компьютере, и в зависимости от типа запроса передает его на сетевой сервер для обработки или определяет, что этот запрос будет выполняться локально.

1.2. Поддержка сетей на основе ОС Windows 2000. Уровни OSI и сетевые компоненты ОС Windows 2000. Сетевые API

Рассмотрим механизмы построения сетевой операционной системы на примере ОС Windows 2000.

Эталонная модель OSI (The OSI Reference Model)

Чтобы помочь поставщикам в стандартизации и интеграции сетевого программного обеспечения в 1974 the International Organization for Standardization (ISO) определила программную модель пересылки сообщений между компьютерами. Результатом явилась the Open Systems Interconnection (OSI) – эталонная модель. Модель определяет семь уровней программного обеспечения (Рис.1).

DIV_ADBLOCK212">

Пунктирными линиями на рисунке показаны протоколы, применяемые для передачи запроса на удаленную машину. Каждый сетевой уровень считает, что он взаимодействует с эквивалентным уровнем на другой машине, который использует тот же протокол. Набор протоколов, передающих запросы по сетевым уровням, называется стеком протоколов.

Сетевые компоненты Windows 2000 (Networking Components)

На рис. 2 представлена общая схема сетевых протоколов Windows 2000, их соответствие уровням эталонной модели, а также протоколы, используемые различными уровнями. Как видно, между уровнями модели и сетевыми компонентами нет точного соответствия. Некоторые компоненты охватывают несколько уровней. Далее приводится список и краткое описание:

1) Networking(Сетевые) API обеспечивают независимое от протоколов взаимодействие приложений через сеть. Networking API реализуются либо в режиме ядра и пользовательском режиме, либо только в пользовательском. Некоторые networking API являются оболочками других API и реализуют специфическую модель программирования или предоставляют дополнительные сервисы. (Термином networking API обозначаются любые программные интерфейсы, представляемые сетевым программным обеспечением);

2) клиенты TDI (Transport Driver Interface). Драйверы устройств режима ядра, обычно реализующие ту часть сетевого API, которая работает в режиме ядра. Клиенты TDI называются так из-за того, что I/O пакеты запросов ввода-вывода (IRP), которые они посылают драйверам протоколов Windows 2000, форматируются по стандарту Transport Driver Interface standard (документировано в DDK). Этот стандарт определяет общий интерфейс программирования драйверов устройств режима ядра;

3) транспорты TDI. Представляют собой драйверы протоколов режима ядра и часто называются транспортами, (Network Driver Interface Specification), NDIS-драйверами протоколов или драйверами протоколов. Они принимают IRP от клиентов TDI и обрабатывают запросы, представленные этими IRP. Обработка запросов может потребовать взаимодействия через сеть с другими равноправными компьютерами, в этом случае транспорт TDI добавляет к данным IRP заголовки, специфические для конкретного протокола (TCP, UDP, IPX), и взаимодействует с драйверами адаптеров через функции NDIS (also documented in the DDK). В общем, транспорты TDI связывают приложения через сеть, выполняя такие операции, как сегментация сообщений, их восстановление, упорядочение, подтверждение и повторная передача;

4) библиотека NDIS (Ndis. sys). Инкапсулирует функциональность для драйверов адаптеров, скрывая от них специфику среды Windows 2000, работающей в режиме ядра. NDIS library экспортирует функции для транспортов TDI, а также функции поддержки для драйверов адаптеров;

5) минипорт – драйверы NDIS. Драйверы режима ядра, отвечающие за организацию интерфейсов между TDI transports и конкретными сетевыми адаптерами. NDIS miniport drivers пишутся так, чтобы они были заключены в оболочку Windows 2000 NDIS library. Такая инкапсуляция обеспечивает межплатформенную совместимость с потребительскими версиями Windows. NDIS miniport drivers не обрабатывают process IRP; а регистрируют интерфейс таблицы вызовов NDIS library, которая содержит указатели на функции, соответствующие функциям, экспортируемым библиотекой NDIS для TDI transports. NDIS miniport drivers взаимодействуют с сетевыми адаптерами, используя функции NDIS library, которые вызывают соответствующие (HAL) функции.

Примечание: Диспетчер ввода-вывода (I/O manager) определяет модель доставки запросов на ввод-вывод драйверам устройств. Большинство запросов ввода-вывода представляется I/O пакетами запросов ввода-вывода (I/O request packets IRP), передаваемых от одного компонента подсистемы ввода-вывода другому. IRP – это структура данных, которая содержит информацию, полностью описывающую запрос ввода-вывода.

Фактически четыре нижних сетевых уровня часто обозначают собирательным термином «транспорт», а компоненты, расположенные на трех верхних уровнях – термином « пользователи транспорта».

DIV_ADBLOCK215">

Протокол SMB является протоколом прикладного уровня, включающим сетевой уровень и уровень представления.

SMB реализует:

1) установление сессии;

2) файловый сервис;

3) сервис печати;

4) сервис сообщений.

CIFS – открытый Microsoft стандарт (документированный в Platform SDK), который позволяет другим платформам взаимодействовать с Windows 2000 файловым сервером и с Windows 2000 файловым клиентом. Например, Samba позволяет UNIX системам выступать в роли файлового сервера для Windows 2000 клиента и UNIX приложениям получать доступ к файлам, хранящимся в системах под управлением Windows 2000 систем. Другие поддерживающие CIFS платформы включают DEC VMS и Apple Macintosh.

Совместное использование файлов в Windows 2000 основывается на редиректоре (redirector FSD - redirector, для краткости), который выполняется на клиентской машине и взаимодействует с FSD redirector сервера. FSD перехватывает запрос Win32 file I/O, направленный в файлы, расположенные на сервере, и передает CIFS messages файловой системе сервера. Сервер получает CIFS messages и преобразует их обратно в запросы на операцию ввода-вывода, которые он выдает локальным FSDs, таким как NTFS.

Поскольку они интегрированны с подсистемой ввода-вывода Windows 2000 (I/O system), redirector and server FSDs имеют некоторые преимущества перед альтернативной реализацией файловых серверов:

1) они могут напрямую взаимодействовать с TDI transports и локальными FSD;

2) они бесшовно интегрируются с диспетчером кеша, что позволяет кешировать данные с файл-сервера на клиентских системах.

Приложения могут использовать стандартные Win32 file I/O функции, такие как CreateFile, ReadFile, and WriteFile для доступа к удаленным файлам.

В Windows 2000 redirector server FSD используют стандартные правила именования сетевых ресурсов, применяемые всеми файл-серверами и клиентскими программами режима ядра. Если подключение к сетевому ресурсу производится по букве диска, имена сетевых файлов указываются также как локальные. Тем не менее, redirector также поддерживает UNC имена

Как server FSD, так и redirector имеют Win32 сервисы, Server and Workstation, выполняемые в процессе service control manager (SCM) и предоставляющие драйверам интерфейсы административного управления.

Примечание:

Можно реализовать серверное приложение как простую исполняемую программу, но можно использовать особый вид – служба (сервис). Служба – это приложение, содержащее дополнительную инфраструктуру, которая позволяет SCM управлять этим приложениям. Все серверные приложения, поставляемые с системой, работают как службы.

Интерфейс транспортных драйверов (TDI)

Открытая архитектура сетевых средств Windows NT обеспечивает работу своих рабочих станций (и серверов) в гетерогенных сетях не только путем предоставления возможности динамически загружать и выгружать сетевые средства, но и путем непосредственного переключения с программных сетевых средств, ориентированных на взаимодействие с одним типом сетей, на программные средства для другого типа сетей в ходе работы системы. Windows NT поддерживает переключение программных средств на трех уровнях:

1) на уровне редиректоров - каждый редиректор предназначен для своего протокола (SMP, NCP, NFS, VINES);

2) на уровне драйверов транспортных протоколов, предоставляя для них и для редиректоров стандартный интерфейс TDI;

3) на уровне драйверов сетевых адаптеров - со стандартным интерфейсом NDIS 3.0.

Для доступа к другим типам сетей в Windows NT, помимо встроенного, могут загружаться дополнительные редиректоры. Специальные компоненты Windows NT решают, какой редиректор должен быть вызван для обслуживания запроса на удаленный ввод-вывод. За последние десятилетия получили распространение различные протоколы передачи информации по сети. И хотя Windows NT поддерживает не все эти протоколы, она, по крайней мере, разрешает включать их поддержку.

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

TDI позволяет редиректорам оставаться независимым от транспорта. Таким образом, одна версия редиректора может пользоваться любым транспортным механизмом. TDI обеспечивает набор функций, которые редиректоры могут использовать для пересылки любых типов данных с помощью транспортного уровня. TDI поддерживает как связи с установлением соединения (виртуальные связи), так и связи без установления соединения (дейтаграммные связи). Хотя LAN Manager использует связи с установлением соединений, Novell IPX является примером сети, которая использует связь без установления соединения. Microsoft изначально обеспечивает транспорты - NetBEUI (NetBIOS Extended User Interface), TCP/IP, IPX/SPX, DECnet и AppleTalk.

Исходя из описанного выше, представим следующие выводы.

Интерфейс транспортных драйверов (TDI) - это общий интерфейс, позволяющий таким компонентам, как редиректор и сервер связываться с различными сетевыми транспортами, т. е. оставаться независимыми от транспорта. Отметим, что (TDI) – это не драйвер, а стандарт для передачи сообщений между уровнями сетевой архитектуры. Microsoft определила стандарт TDI, чтобы драйверам сетевых протоколов не приходилось использовать отдельные интерфейсы для каждого необходимого им транспортного протокола.

Как уже говорилось, Интерфейс транспортных драйверов (TDI) по сути представляет правила формирования сетевых запросов в IRP, а также выделения сетевых адресов и коммуникационных соединений. Транспортные протоколы, отвечающие данному стандарту, экспортируют интерфейс TDI своим клиентам, в число которых входят драйверы сетевых API и редиректор. Транспортный протокол, реализованный в виде драйвера устройства, называется транспортами TDI, а поскольку они есть драйверы, то преобразуют получаемые от клиентов запросы в IRP. Интерфейс транспортных драйверов (TDI образуют функции поддержки из библиотеки \ winnt\system32\drivers\tdi. sys.

Библиотека NDIS (Ndis . sys )

Введем также понятие граничного слоя. Граница – это унифицированный интерфейс между функциональными уровнями в модели сетевой архитектуры. Создание границ как разделов между сетевыми уровнями облегчает третьим фирмам разработку сетевых драйверов и сервисов в среде открытых систем.

Сетевые адаптеры поставляются вместе с сетевыми драйверами, которые раньше часто были рассчитаны на взаимодействие с определенным типом транспортного протокола. Так как Windows NT позволяет загружать драйверы различных транспортных протоколов, то производители сетевых адаптеров, использующие такой подход, должны были писать различные варианты одного и того же драйвера, рассчитанные на связь с разными протоколами транспортного уровня.

Чтобы помочь производителям избежать этого, Windows NT обеспечивает интерфейс и программную среду, называемые "спецификация интерфейса сетевого драйвера " (NDIS), которые экранируют сетевые драйверы от деталей различных транспортных протоколов. Самый верхний уровень драйвера сетевого адаптера должен быть написан в соответствии с рекомендациями NDIS. В этом случае пользователь может работать с сетью TCP/IP и сетью NetBEUI (или DECnet, NetWare, VINES и т. п.), используя один сетевой адаптер и один сетевой драйвер. Среда NDIS использовалась в сетях LAN Manager, но для Windows NT она была обновлена.

Через свою нижнюю границу драйвер сетевого адаптера обычно взаимодействует непосредственно с адаптером или адаптерами, которые он обслуживает. Драйвер сетевого адаптера, реализованный для среды NDIS, управляет адаптером не непосредственно, а использует для этого функции, предоставляемые NDIS (например, для запуска ввода-вывода или обработки прерываний). Таким образом, среда NDIS образует некую оболочку, которая позволяет достаточно просто переносить драйверы сетевых адаптеров из одной ОС в другую. NDIS позволяет сетевым драйверам не содержать встроенных знаний о процессоре или операционной системе, на которых он работает.

Безопасность в сети и доменная структура

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

Корпорация Microsoft включила требования безопасности в состав начальной спецификации для разработки Windows NT. Вопросы безопасности в Windows NT имеют первостепенное значение. Модель безопасности включает компоненты для контроля доступа к объектам (таким как файлы и разделяемые принтеры). Эти компоненты определяют, кто и к каким объектам может получить доступ, какое действие может быть произведено над объектом (например, запись в файл и т. д.), и какие события подлежат аудиту.

Безопасность сети Windows NT включает и доверительные отношения между доменами, что делает эту операционную систему защищенной наилучшим образом.

Архитектура модели безопасности

На рис. 3 показаны компоненты модели безопасности Windows NT, в число которых входят:

1) процессы входа в систему (Logon processes), которые получают от пользователей запросы на вход. Они включают интерактивный вход, который производится с помощью начального диалогового окна входа, и удаленные процессы входа, которые предоставляют удаленным пользователям доступ к процессам сервера Windows NT;

2) локальная служба безопасности (Local Security Authority, LSA), кото­рая следит за тем, чтобы пользователь имел право на доступ (permission) в систему. Этот компонент является центром подсистемы безопасности Windows NT. Он генерирует маркеры доступа (access tokens), управляет локальной политикой безопасности и обеспечивает интерактивную аутентификацию пользователя. Кроме того, LSA контролирует политику аудита и заносит в журнал аудиторские записи, генерируемые монитором безопасности;

3) диспетчер безопасности пользовательских учетных записей (Security Account Manager, SAM), поддерживающий базу данных учетных записей пользова­телей, также известную под названием базы данных каталога (directory database). Эта база данных содержит информацию по всем учетным записям пользователей и групп. SAM обеспечивает сервис проверки пользователей, который используется LSA;

4) монитор безопасности (Security Reference Monitor), который проверяет, имеет ли пользователь разрешение на доступ к объекту и право на операцию, которую он пытается выполнить. Этот компонент принудительным образом осуществляет проверку уровня доступа и проводит политику аудита, определенную LSA. Он обеспечивает сервис для режимов ядра и пользователя, выполняющий проверку наличия необходимого уровня доступа для всех пользователей и процессов, пытающихся получить доступ к объекту. В случае необходимости этот компонент также генерирует записи в файл аудита.

В совокупности все эти компоненты также известны, как подсистема безопасности. Эта подсистема, называемая интегральной подсистемой (integral subsystem), не является подсистемой среды (environmental subsystem), потому что она распространяет свое действие на всю операционную систему Windows NT.

NFS: удобная и перспективная сетевая файловая система

Сетевая файловая система – это сетевая абстракция поверх обычной файловой системы, позволяющая удаленному клиенту обращаться к ней через сеть так же, как и при доступе к локальным файловым системам. Хотя NFS не является первой сетевой системой, она сегодня развилась до уровня наиболее функциональной и востребованной сетевой файловой системы в UNIX®. NFS позволяет организовать совместный доступ к общей файловой системе для множества пользователей и обеспечить централизацию данных для минимизации дискового пространства, необходимого для их хранения.

Эта статья начинается с краткого обзора истории NFS, а затем переходит к исследованию архитектуры NFS и путей её дальнейшего развития.

Краткая история NFS

Первая сетевая файловая система называлась FAL (File Access Listener - обработчик доступа к файлам) и была разработана в 1976 году компанией DEC (Digital Equipment Corporation). Она являлась реализацией протокола DAP (Data Access Protocol – протокол доступа к данным) и входила в пакет протоколов DECnet. Как и в случае с TCP/IP, компания DEC опубликовала спецификации своих сетевых протоколов, включая протокол DAP.

NFS была первой современной сетевой файловой системой, построенной поверх протокола IP. Её прообразом можно считать экспериментальную файловую систему, разработанную в Sun Microsystems в начале 80-х годов. Учитывая популярность этого решения, протокол NFS был представлен в качестве спецификации RFC и впоследствии развился в NFSv2. NFS быстро утвердилась в качестве стандарта благодаря способности взаимодействовать с другими клиентами и серверами.

Впоследствии стандарт был обновлен до версии NFSv3, определенной в RFC 1813. Эта версия протокола была более масштабируема, чем предыдущие, и поддерживала файлы большего размера (более 2 ГБ), асинхронную запись и TCP в качестве транспортного протокола. NFSv3 задала направление развития файловых систем для глобальных (WAN) сетей. В 2000 году в рамках спецификации RFC 3010 (переработанной в версии RFC 3530) NFS была перенесена в корпоративную среду. Sun представила более защищенную NFSv4 c поддержкой сохранения состояния (stateful) (предыдущие версии NFS не поддерживали сохранение состояния, т.е. относились к категории stateless). На текущий момент последней версией NFS является версия 4.1, определенная в RFC 5661, в которой в протокол посредством расширения pNFS была добавлена поддержка параллельного доступа для распределенных серверов.

История развития NFS, включая конкретные RFC, описывающие её версии, показана на рисунке 1.


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

Архитектура NFS

NFS использует стандартную архитектурную модель "клиент-сервер" (как показано на рисунке 2). Сервер отвечает за реализацию файловой системы совместного доступа и хранилища, к которому подключаются клиенты. Клиент реализует пользовательский интерфейс к общей файловой системе, смонтированной внутри локального файлового пространства клиента.

Рисунок 2. Реализация модели "клиент-сервер" в архитектуре NFS

В ОС Linux® виртуальный коммутатор файловой системы (virtual file system switch - VFS) предоставляет средства для одновременной поддержки на одном хосте нескольких файловых систем (например, файловой системы ISO 9660 на CD-ROM и файловой системы ext3fs на локальном жестком диске). Виртуальный коммутатор определяет, к какому накопителю выполняется запрос, и, следовательно, какая файловая система должна использоваться для обработки запроса. Поэтому NFS обладает такой же совместимостью, как и другие файловые системы, применяющиеся в Linux. Единственное отличие NFS состоит в том, что запросы ввода/вывода вместо локальной обработки на хосте могут быть направлены для выполнения в сеть.

VFS определяет, что полученный запрос относится к NFS, и передает его в обработчик NFS, находящийся в ядре. Обработчик NFS обрабатывает запрос ввода/вывода и транслирует его в NFS-процедуру (OPEN , ACCESS , CREATE , READ , CLOSE , REMOVE и т.д.). Эти процедуры, описанные в отдельной спецификации RFC, определяют поведение протокола NFS. Необходимая процедура выбирается в зависимости от запроса и выполняется с помощью технологии RPC (вызов удаленной процедуры). Как можно понять по названию, RPC позволяет осуществлять вызовы процедур между различными системами. RPC-служба соединяет NFS-запрос с его аргументами и отправляет результат на соответствующий удаленный хост, а затем следит за получением и обработкой ответа, чтобы вернуть его инициатору запроса.

Также RPC включает в себя важный уровень XDR (external data representation – независимое представление данных), гарантирующий, что все пользователи NFS для одинаковых типов данных используют один и тот же формат. Когда некая платформа отправляет запрос, используемый ею тип данных может отличаться от типа данных, используемого на хосте, обрабатывающего этот запрос. Технология XDR берет на себя работу по преобразованию типов в стандартное представление (XDR), так что платформы, использующие разные архитектуры, могут взаимодействовать и совместно использовать файловые системы. В XDR определен битовый формат для таких типов, как float , и порядок байтов для таких типов, как массивы постоянной и переменной длины. Хотя XDR в основном известна благодаря применению в NFS, это спецификация может быть полезна во всех случаях, когда приходится работать в одной среде с различными архитектурами.

После того как XDR переведет данные в стандартное представление, запрос передается по сети с помощью определенного транспортного протокола. В ранних реализациях NFS использовался протокол UDP, но сегодня для обеспечения большей надежности применяется протокол TCP.

На стороне NFS-сервера применяется схожий алгоритм. Запрос поднимается по сетевому стеку через уровень RPC/XDR (для преобразования типов данных в соответствии с архитектурой сервера) и попадает в NFS-сервер, который отвечает за обработку запроса. Там запрос передается NFS-демону для определения целевой файловой системы, которой он адресован, а затем снова поступает в VFS для обращения к этой файловой системе на локальном диске. Полностью схема этого процесса приведена на рисунке 3. При этом локальная файловая система сервера – это стандартная для Linux файловая система, например, ext4fs. По сути NFS – это не файловая система в традиционном понимании этого термина, а протокол удаленного доступа к файловым системам.


Для сетей с большим временем ожидания в NFSv4 предлагается специальная составная процедура (compound procedure ). Эта процедура позволяет поместить несколько RPC-вызовов внутрь одного запроса, чтобы минимизировать затраты на передачу запросов по сети. Также в этой процедуре реализован механизм callback-функций для получения ответов.

Протокол NFS

Когда клиент начинает работать с NFS, первым действием выполняется операция mount , которая представляет собой монтирование удаленной файловой системы в пространство локальной файловой системы. Этот процесс начинается с вызова процедуры mount (одной из системных функций Linux), который через VFS перенаправляется в NFS-компонент. Затем с помощью RPC-вызова функции get_port на удаленном сервере определяется номер порта, который будет использоваться для монтирования, и клиент через RPC отправляет запрос на монтирование. Этот запрос на стороне сервера обрабатывается специальным демоном rpc.mountd , отвечающим за протокол монтирования (mount protocol ). Демон проверяет, что запрошенная клиентом файловая система имеется в списке систем, доступных на данном сервере. Если запрошенная система существует и клиент имеет к ней доступ, то в ответе RPC-процедуры mount указывается дескриптор файловой системы. Клиент сохраняет у себя информацию о локальной и удаленной точках монтирования и получает возможность осуществлять запросы ввода/вывода. Протокол монтирования не является безупречным с точки зрения безопасности, поэтому в NFSv4 вместо него используются внутренние RPC-вызовы, которые также могут управлять точками монтирования.

Для считывания файла его необходимо сначала открыть. В RPC нет процедуры OPEN , вместо этого клиент просто проверяет, что указанные файл и каталог существуют в смонтированной файловой системе. Клиент начинает с выполнения RPC-запроса GETATTR к каталогу, в ответ на который возвращаются атрибуты каталога или индикатор, что каталог не существует. Далее, чтобы проверить наличие файла, клиент выполняет RPC-запрос LOOKUP . Если файл существует, для него выполняется RPC-запрос GETATTR , чтобы узнать атрибуты файла. Используя информацию, полученную в результате успешных вызовов LOOKUP и GETATTR , клиент создает дескриптор файла, который предоставляется пользователю для выполнения будущих запросов.

После того как файл идентифицирован в удаленной файловой системе, клиент может выполнять RPC-запросы типа READ . Этот запрос состоит из дескриптора файла, состояния, смещения и количества байт, которое следует считать. Клиент использует состояние (state ), чтобы определить может ли операция быть выполнена в данный момент, т.е. не заблокирован ли файл. Смещение (offset ) указывает, с какой позиции следует начать чтение, а счетчик байт (count ) определяет, сколько байт необходимо считать. В результате RPC-вызова READ сервер не всегда возвращает столько байт, сколько было запрошено, но вместе с возвращаемыми данными всегда передает, сколько байт было отправлено клиенту.

Инновации в NFS

Наибольший интерес представляют две последние версии NFS – 4 и 4.1, на примере которых можно изучить наиболее важные аспекты эволюции технологии NFS.

До появления NFSv4 для выполнения таких задач по управлению файлами, как монтирование, блокировка и т.д. существовали специальные дополнительные протоколы. В NFSv4 процесс управления файлами был упрощен до одного протокола; кроме того, начиная с этой версии UDP больше не используется в качестве транспортного протокола. NFSv4 включает поддержку UNIX и Windows®-семантики доступа к файлам, что позволяет NFS "естественным" способом интегрироваться в другие операционные системы.

В NFSv4.1 для большей масштабируемости и производительности была введена концепция параллельной NFS (parallel NFS - pNFS). Чтобы обеспечить больший уровень масштабируемости, в NFSv4.1 реализована архитектура, в которой данные и метаданные (разметка ) распределяются по устройствам аналогично тому, как это делается в кластерных файловых системах. Как показано на , pNFS разделяет экосистему на три составляющие: клиент, сервер и хранилище. При этом появляются два канала: один для передачи данных, а другой для передачи команд управления. pNFS отделяет данные от описывающих их метаданных, обеспечивая двухканальную архитектуру. Когда клиент хочет получить доступ к файлу, сервер отправляет ему метаданные с "разметкой". В метаданных содержится информация о размещении файла на запоминающих устройствах. Получив эту информацию, клиент может обращаться напрямую к хранилищу без необходимости взаимодействовать с сервером, что способствует повышению масштабируемости и производительности. Когда клиент заканчивает работу с файлом, он подтверждает изменения, внесенные в файл и его "разметку". При необходимости сервер может запросить у клиента метаданные с разметкой.

С появлением pNFS в протокол NFS было добавлено несколько новых операций для поддержки такого механизма. Метод LayoutGet используется для получения метаданных с сервера, метод LayoutReturn "освобождает" метаданные, "захваченные" клиентом, а метод LayoutCommit загружает "разметку", полученную от клиента, в хранилище, так что она становится доступной другим пользователям. Сервер может отозвать метаданные у клиента с помощью метода LayoutRecall . Метаданные с "разметкой" распределяются между несколькими запоминающими устройствами, чтобы обеспечить параллельный доступ и высокую производительность.


Данные и метаданные хранятся на запоминающих устройствах. Клиенты могут выполнять прямые запросы ввода/вывода на основе полученной разметки, а сервер NFSv4.1 хранит метаданные и управляет ими. Сама по себе эта функциональность и не нова, но в pNFS была добавлена поддержка различных методов доступа к запоминающим устройствам. Сегодня pNFS поддерживает использование блочных протоколов (Fibre Channel), объектных протоколов и собственно NFS (даже не в pNFS-форме).

Развитие NFS продолжается, и в сентябре 2010 года были опубликованы требования к NFSv4.2. Некоторые из нововведений связаны с наблюдающейся миграцией технологий хранения данных в сторону виртуализации. Например, в виртуальных средах с гипервизором весьма вероятно возникновение дублирования данных (несколько ОС выполняют чтение/запись и кэширование одних и тех же данных). В связи с этим желательно, чтобы система хранения данных в целом понимала, где происходит дублирование. Такой подход поможет сэкономить пространство в кэше клиента и общую емкость системы хранения. В NFSv4.2 для решения этой проблемы предлагается использовать "карту блоков, находящихся в совместном доступе" (block map of shared blocks). Поскольку современные системы хранения все чаще оснащаются собственными внутренними вычислительными мощностями, вводится копирование на стороне сервера, позволяющее снизить нагрузку при копировании данных во внутренней сети, когда это можно эффективно делать на самом запоминающем устройстве. Другие инновации включают в себя субфайловое кэширование для флэш-памяти и рекомендации по настройке ввода-вывода на стороне клиента (например, с использованием mapadvise).

Альтернативы NFS

Хотя NFS – самая популярная сетевая файловая система в UNIX и Linux, кроме нее существуют и другие сетевые файловые системы. На платформе Windows® чаще всего применяется SMB, также известная как CIFS ; при этом ОС Windows также поддерживает NFS, равно как и Linux поддерживает SMB.

Одна из новейших распределенных файловых систем, поддерживаемых в Linux - Ceph - изначально спроектирована как отказоустойчивая POSIX-совместимая файловая система. Дополнительную информацию о Ceph можно найти в разделе .

Стоит также упомянуть файловые системы OpenAFS (Open Source-версия распределенной файловой системы Andrew, разработанной в университете Карнеги-Меллона и корпорации IBM), GlusterFS (распределенная файловая система общего назначения для организации масштабируемых хранилищ данных) и Lustre (сетевая файловая система с массовым параллелизмом для кластерных решений). Все эти системы с открытым исходным кодом можно использовать для построения распределенных хранилищ.

Заключение

Развитие файловой системы NFS продолжается. Подобно ОС Linux, подходящей для поддержки и бюджетных, и встраиваемых, и высокопроизводительных решений, NFS предоставляет архитектуру масштабируемых решений для хранения данных, подходящих как отдельным пользователям, так и организациям. Если посмотреть на путь, уже пройденный NFS, и перспективы её дальнейшего развития, становится понятно, что эта файловая система будет продолжать изменять наши взгляды на то, как реализуются и используются технологии хранения файлов.

Глава 29 NFS: сетевая файловая система

Введение

В этой главе мы рассмотрим сетевую файловую систему ( NFS - Network File System), популярное приложение, которое предоставляет приложениям клиентов прозрачный доступ к файлам. Краеугольным камнем NFS является Sun RPC: вызов удаленной процедуры (Remote Procedure Call), что мы и опишем в первую очередь.

Программе клиента не требуется специальных средств, чтобы воспользоваться NFS. Ядро определяет что файл находится на NFS сервере и автоматически генерирует RPC вызов, для того чтобы получить доступ к файлу.

Мы не будем подробно рассматривать, как реализуется доступ к файлам, а рассмотрим, как при этом используются протоколы Internet, особенно UDP.

Вызов удаленной процедуры компании Sun

В большинстве случаев задачи сетевого программирования решаются путем написания программ приложений, которые вызывают функции, предоставляемые системой, чтобы осуществить конкретные сетевые операции. Например, одна функция осуществляет активное открытие TCP, другая пассивное открытие TCP, третья посылает данные по TCP соединению, четвертая устанавливает конкретные опции протокола (включает TCP таймер "оставайся в живых") и так далее. В разделе "Интерфейсы прикладного программирования" главы 1 мы упоминали, что существует два популярных набора функций для сетевого программирования (прикладной программный интерфейс, API), это сокеты и TLI. Программный интерфейс, используемый клиентом, и программный интерфейс, используемый сервером, могут отличаться, так же как и операционные системы, которые функционируют у клиента и сервера. Именно коммуникационный и прикладной протоколы определяют, сможет ли конкретный клиент общаться с сервером. Unix клиент, написанный на C, использующий сокеты в качестве программного интерфейса, и TCP - в качестве коммуникационного протокола, может общаться с сервером на мейнфрейме, написанным на COBOLе с использованием других API и TCP, если оба хоста подключены к сети и оба имеют реализацию TCP/IP.

Обычно клиент посылает серверу команды, а сервер отправляет клиенту отклики. Все рассмотренные нами приложения, - Ping, Traceroute, демоны маршрутизации, клиенты и сервера DNS, TFTP, BOOTP, SNMP, Telnet, FTP, SMTP - все построены именно таким образом.

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

  1. Когда клиент вызывает удаленную процедуру, вызывается функция на локальном хосте, которая сгенерирована пакетом RPC. Эта функция называется client stub. client stub упаковывает аргументы процедуры в сетевое сообщение и отправляет сообщение серверу.
  2. server stub на хосте сервера получает сетевое сообщение. Аргументы извлекаются из сетевого сообщения, и осуществляется вызов процедуры сервера, написанной прикладным программистом.
  3. Функция сервера возвращает управление server stubу, который, в свою очередь, принимает полученные значения, упаковывает их в сетевое сообщение и отправляет сообщение обратно к client stub.
  4. client stub возвращает приложению клиента значения из сетевого сообщения.

Сетевое программирование, использующее stubы и библиотечные RPC подпрограммы использует интерфейсы прикладного программирования API (сокеты или TLI), однако пользовательские приложения (программа клиента и процедуры сервера, вызываемые клиентом) никогда не обращаются к API. Приложению клиента достаточно вызывать процедуру сервера, при этом все детали реализации спрятаны пакетом RPC, client stubом и server stubом.

Пакеты RPC имеют следующие положительные стороны.

  • Программирование становится легче, так как не приходится решать задачи сетевого программирования (а если и приходится, то совсем немного). Прикладные программисты просто пишут программу клиента и процедуры сервера, которые вызывает клиент.
  • Если используется ненадежный протокол, такой как UDP, все детали, а именно тайм-ауты и повторные передачи обрабатываются пакетом RPC. Это, в свою очередь, упрощает пользовательское приложение.
  • Библиотека RPC обрабатывает необходимое преобразование аргументов и возвращаемых значений. Например, если аргументы состоят из целых чисел и чисел с плавающей точкой, пакет RPC обработает все различия между представлением целых чисел и чисел с плавающей точкой на клиенте и сервере. Благодаря этому упрощается реализация клиентов и серверов для функционирования в разнородных средах.

Программирование RPC подробно описано в главе 18 . Два наиболее популярных RPC пакета это Sun RPC и RPC пакет в Open Software Foundation"s ( OSF) Distributed Computing Environment ( DCE). Мы рассмотрим, как осуществляется вызов процедуры, как выглядит возвращаемое сообщение и как это соотносится с пакетом Sun RPC, так как именно этот пакет используется в сетевой файловой системе. Версия 2 Sun RPC описана в RFC 1057 [ Sun Microsystems 1988a].

Существует два вида Sun RPC. Одна версия построена с использованием API сокет и работает с TCP и UDP. Другая называется TI-RPC (независимо от транспорта - transport independent), построена с использованием TLI API и работает с любыми транспортными уровнями, предоставляемыми ядром. С нашей точки зрения между ними нет никакой разницы, так как в этой главе мы рассматриваем только TCP и UDP.

На рисунке 29.1 показан формат сообщения вызова процедуры RPC, с использованием UDP.

Рисунок 29.1 Сообщения вызова процедуры RPC в формате UDP датаграммы.

Стандартные IP и UDP заголовки показаны раньше (рисунок 3.1 и рисунок 11.2). Все, что следует после UDP заголовка, определяется пакетом RPC.

Идентификатор транзакции ( XID - transaction ID) устанавливается клиентом и возвращается сервером. Когда клиент получает отклик, он сравнивает XID, возвращенный сервером, с XID отправленного запроса. Если они не совпадают, клиент отбрасывает сообщение и ожидает прихода следующего. Каждый раз, когда клиент выдает новый RPC, он меняет XID. Однако если клиент передает RPC повторно (если отклик не был получен), XID не меняется.

Переменная call равна 0 для вызова и 1 для отклика. Текущая версия RPC (RPC version) равна 2. Три следующие переменные, номер программы (program number), номер версии (version number) и номер процедуры (procedure number), идентифицируют конкретную процедуру, которая должна быть вызвана на сервере.

Полномочия (credentials) идентифицируют клиента. В некоторых примерах это поле остается незаполненным, а в других здесь можно встретить цифровой идентификатор пользователя и идентификатор группы к который он принадлежит. Сервер может заглянуть в полномочия и решить, обработать ли запрос или нет. Проверка (verifier) используется для защищенного RPC (Secure RPC), которое использует DES шифрование. Несмотря на то, что поля полномочий и проверки это поля с переменной длиной, их длина передается как часть поля.

Дальше следуют параметры процедуры. Их формат зависит от того, как приложение определяет удаленную процедуру. Как получатель (server stub) узнает размер параметров? Так как используется UDP, размер параметров можно рассчитать как размер UDP датаграммы минус длина всех полей вплоть до поля проверки. Когда вместо UDP используется TCP, понятия фиксированной длины не существует, так как TCP это поток байтов без разделителей записей. В подобном случае, между TCP заголовком и XID появляется 4-байтовое поле длины, из которого приемник узнает длину RPC вызова в байтах. Это позволяет, если необходимо, послать сообщение вызова RPC в нескольких TCP сегментах. (DNS использует подобную технику; упражнение 4 главы 14.)

На рисунке 29.2 показан формат RPC отклика. Он отправляется от server stub к client stub, когда удаленная процедура завершает свою работу.

Рисунок 29.2 Формат сообщения отклика процедуры RPC как UDP датаграмма.

XID вызова просто копируется в XID отклика. В поле reply находится 1, по этому полю проводится различие между вызовом и откликом. Поле статуса (status) содержит нулевое значение, если сообщение вызова было принято. (Сообщение может быть отброшено, если номер версии RPC не равен 2 или если сервер не может аутентифицировать клиента.) Поле проверки (verifier) используется в случае защищенного RPC, чтобы указать сервер.

В поле статуса приема (accept status) находится нулевое значение, если все нормально. Ненулевое значение может указывать, например, на неверный номер версии или неверный номер процедуры. Если вместо UDP используется TCP, то, как и в случае сообщения вызова RPC, между TCP заголовком и XID посылается 4-байтовое поле длины.

XDR: представление внешних данных

Представление внешних данных ( XDR - External Data Representation) это стандарт, используемый для кодирования значений в RPC вызове и отклике сообщениях - полей заголовка RPC (XID, номер программы, статус приема и так далее), параметров процедуры и результатов процедуры. Стандартный способ кодирования данных позволяет клиенту вызвать процедуру в системе с отличной архитектурой. XDR определен в RFC 1014 [ Sun Microsystems 1987].

XDR определяет определенное количество типов данных и точный способ того, как они передаются в RPC сообщении (порядок битов, порядок байтов и так далее). Отправитель должен построить RPC сообщение в XDR формате, тогда получатель конвертирует XDR формат в исходное представление. (В тот формат, который принят для его системы.) Мы видим, например, на рисунках 29.1 и 29.2, что все целые значения, которые мы показали (XID, вызов, номер программы и так далее), это 4-байтовые целые числа. И действительно, все целые в XDR занимают 4 байта. XDR поддерживает и другие типы данных, включая целые без знака, логические, числа с плавающей точкой, массивы фиксированной длины, массивы переменной длины и структуры.

Соответствие портов

Программы RPC сервера, содержащие удаленные процедуры, используют динамически назначаемые порты, а не заранее известные порты. Это требует "регистрации" в какой-либо форме, для того чтобы постоянно иметь информацию, какая динамически назначаемый порт использует та или иная RPC программа. В Sun RPC этот регистратор называется преобразователь портов (port mapper). (Port mapper - это сервер, который конвертирует номера RPC программ в номера портов протоколов DARPA. Этот сервер обязательно должен быть запущен, чтобы можно было исполнить RPC вызов.)

Термин "порт" (port) в названии происходит от номеров портов TCP и UDP, характеристики семейства протоколов Internet. Так как TI-RPC работает поверх любых транспортных уровней, а не только поверх TCP и UDP, название port mapper в системах, использующих TI-RPC ( SVR4 и Solaris 2.2, например), было преобразовано в rpcbind. Однако мы будем продолжать использовать более привычное - port mapper.

В действительности, сам преобразователь портов должен иметь заранее известный порт: UDP порт 111 и TCP порт 111. Преобразователь портов - это всего лишь программа RPC сервера. Он имеет номер программы (100000), номер версии (2), TCP порт 111 и UDP порт 111. Серверы регистрируют друг друга в преобразователе портов, используя RPC вызовы, а клиенты запрашивают преобразователь портов, используя RPC вызовы. Преобразователь портов предоставляет четыре процедуры сервера:

  1. PMAPPROC_SET. Вызывается RPC сервером при старте, чтобы зарегистрировать номер программы, номер версии и протокол в преобразователе портов.
  2. PMAPPROC_UNSET. Вызывается сервером, чтобы удалить ранее зарегистрированное преобразование.
  3. PMAPPROC_GETPORT. Вызывается RPC клиентом при старте, чтобы получить номер порта для заданного номера программы, номера версии и протокола.
  4. PMAPPROC_DUMP. Возвращает все пункты (номер программы, номер версии, протокол и номер порта) в базу данных преобразователя портов.

Когда стартует программа сервер RPC и позже, когда она вызывается программой клиента RPC, осуществляются следующие шаги.

  1. Преобразователь портов должен стартовать первым, обычно при загрузке системы. При этом создается конечная точка TCP и осуществляется пассивное открытие TCP порта 111. Также создается конечная точка UDP, которая находится в ожидании, когда на UDP порт 111 прибудет UDP датаграмма.
  2. При старте программа сервера RPC создает конечную точку TCP и конечную точку UDP для каждой поддерживаемой версии программы. (Программа RPC может поддерживать несколько версий. Клиент указывает требуемую версию при вызове процедуры сервера.) Динамически назначаемый номер порта закрепляется за каждой конечной точкой. (Нет никакой разницы, одинаковые ли номера портов TCP и UDP или разные.) Сервер регистрирует каждую программу, версию, протокол и номер порта, осуществляя удаленной вызов процедуры преобразователя портов PMAPPROC_SET.
  3. Когда стартует программа клиента RPC, она вызывает процедуру преобразователя портов PMAPPROC_GETPORT, чтобы получить динамически назначаемый номер порта для заданной программы, версии и протокола.
  4. Клиент отправляет сообщение вызова RPC на номер порта, полученный в пункте 3. Если используется UDP, клиент просто посылает UDP датаграмму, содержащую сообщение вызова RPC (рисунок 29.1), на номер UDP порта сервера. В ответ сервер отправляет UDP датаграмму, содержащую сообщение RPC отклика (рисунок 29.2). Если используется TCP, клиент осуществляет активное открытие на номер TCP порта сервера и затем посылает сообщение вызова RPC по соединению. Сервер отвечает сообщением отклика RPC по соединению.

Программа rpcinfo(8) печатает все текущие настройки преобразователя портов. (Здесь происходит вызов процедуры преобразователя портов PMAPPROC_DUMP.) Ниже показан обычный вывод:

Sun % /usr/etc/rpcinfo -p
program vers proto port
100005 1 tcp 702 mountd демон монтирования NFS
100005 1 udp 699 mountd
100005 2 tcp 702 mountd
100005 2 udp 699 mountd

100003 2 udp 2049 nfs сам NFS

100021 1 tcp 709 nlockmgr менеджер блокирования NFS
100021 1 udp 1036 nlockmgr
100021 2 tcp 721 nlockmgr
100021 2 udp 1039 nlockmgr
100021 3 tcp 713 nlockmgr
100021 3 udp 1037 nlockmgr

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

Доступ к обеим версиям монтирующего демона можно получить через один и тот же номер TCP порта (702) и один и тот же номер UDP порта (699), однако каждая версия блокирующего менеджера имеет свой собственный номер порта.

Протокол NFS

NFS предоставляет клиентам прозрачный доступ к файлам и файловой системе сервера. Это отличается от FTP (глава 27), который обеспечивает передачу файлов. С помощью FTP осуществляется полное копирование файла. NFS осуществляет доступ только к тем частям файла, к которым обратился процесс, и основное достоинство NFS в том, что он делает этот доступ прозрачным. Это означает, что любое приложение клиента, которое может работать с локальным файлом, с таким же успехом может работать и с NFS файлом, без каких либо модификаций самой программы.

NFS это приложение клиент-сервер, построенное с использованием Sun RPC. NFS клиенты получают доступ к файлам на NFS сервере путем отправки RPC запросов на сервер. Это может быть реализовано с использованием обычных пользовательских процессов - а именно, NFS клиент может быть пользовательским процессом, который осуществляет конкретные RPC вызовы на сервер, который так же может быть пользовательским процессом. Однако, NFS обычно реализуется иначе, это делается по двум причинам. Во-первых, доступ к NFS файлам должен быть прозрачным для клиента. Поэтому, вызовы NFS клиента осуществляются операционной системой клиента от имени пользовательского процесса клиента. Во-вторых, NFS сервера реализованы внутри операционной системы для повышения эффективности работы сервера. Если бы NFS сервер являлся пользовательским процессом, каждый запрос клиента и отклик сервера (включая данные, которые будут считаны или записаны) должен пройти через разделитель между ядром и пользовательским процессом, что вообще довольно дорогое удовольствие.

В этом разделе мы рассмотрим версию 2 NFS, как она документирована в RFC 1094 [ Sun Microsystems 1988b]. Лучшее описание Sun RPC, XDR и NFS дано в [ X/Open 1991]. Подробности использования и администрирования NFS приведены в [ Stern 1991]. Спецификации версии 3 протокола NFS были реализованы в 1993 году, о чем мы поговорим в разделе этой главы.

На рисунке 29.3 показаны типичные настройки NFS клиента и NFS сервера. На этом рисунке необходимо обратить внимание на следующее.

  1. Клиенту безразлично, получает ли он доступ к локальному файлу или к NFS файлу. Ядро определяет это, когда файл открыт. После того как файл открыт, ядро передает все обращения к локальным файлам в квадратик, помеченный как "доступ к локальным файлам", а все ссылки на NFS файлы передаются в квадратик "NFS клиент".
  2. NFS клиент отправляет RPC запросы NFS серверу через модуль TCP/IP. NFS обычно использует UDP, однако более новые реализации могут использовать TCP.
  3. NFS сервер получает запросы от клиента в виде UDP датаграмм на порт 2049. Несмотря на то, что NFS может работать с преобразователем портов, что позволяет серверу использовать динамически назначаемые порты, UDP порт 2049 жестко закреплен за NFS в большинстве реализаций.

Рисунок 29.3 Типичные настройки NFS клиента и NFS сервера.

  • Когда NFS сервер получает запрос от клиента, он передаются локальной подпрограмме доступа к файлу, которая обеспечивает доступ к локальному диску на сервере.
  • Серверу может потребоваться время, для того чтобы обработать запросы клиента. Даже доступ к локальной файловой системе может занять некоторое время. В течение этого времени сервер не хочет блокировать запросы от других клиентов, которые также должны быть обслужены. Чтобы справиться с подобной ситуацией, большинство NFS серверов запускаются несколько раз, то есть внутри ядра существует несколько NFS серверов. Конкретные методы решения зависят от операционной системы. В большинстве ядер Unix систем не "живет" несколько NFS серверов, вместо этого запускается несколько пользовательских процессов (которые обычно называются nfsd), которые осуществляют один системный вызов и остаются внутри ядра в качестве процесса ядра.
  • Точно так же, NFS клиенту требуется время, чтобы обработать запрос от пользовательского процесса на хосте клиента. RPC выдается на хост сервера, после чего ожидается отклик. Для того, чтобы пользовательские процессы на хосте клиента могли в любой момент воспользоваться NFS, существует несколько NFS клиентов, запущенных внутри ядра клиента. Конкретная реализация также зависит от операционной системы. Unix система обычно использует технику, напоминающую NFS сервер: пользовательский процесс, называемый biod, осуществляет один единственный системный вызов и остается внутри ядра как процесс ядра.
  • Большинство Unix хостов может функционировать как NFS клиент и как NFS сервер, или как и то и другое одновременно. Большинство PC реализаций (MS-DOS) имеют только реализации NFS клиента. Большинство IBM мейнфреймов предоставляет только функции NFS сервера.

    NFS в действительности - это нечто большее, чем просто NFS протокол. На рисунке 29.4 показаны различные программы RPC, которые используются с NFS.

    Приложение

    Номер программы

    Номер версии

    Количество процедур

    преобразователь портов
    NFS
    программа mount
    менеджер блокирования
    монитор статуса

    Рисунок 29.4 Различные RPC программы, используемые в NFS.

    Версии, которые мы показали на этом рисунке в виде единиц, найдены в таких системах как SunOS 4.1.3. Новые реализации предоставляют более новые версии некоторых программ. Solaris 2.2, например, также поддерживает версии 3 и 4 преобразователя портов и версию 2 демона mount. SVR4 также поддерживает версию 3 преобразователя портов.

    Демон монтирования вызывается на хосте NFS клиента, перед тем как клиент может получить доступ к файловой системе сервера. Мы опишем этот процесс ниже.

    Менеджер блокирования и монитор статуса позволяют клиенту заблокировать часть файлов, которые находятся на NFS сервере. Эти две программы не зависимы от протокола NFS, потому что блокирование требует идентификации клиента и на хосте клиента, и на сервере, а NFS сам по себе "безразличен". (Ниже мы скажем о безразличности NFS более подробно.) Главы 9, 10 и 11 [ X/Open 1991] документируют процедуры, которые используются менеджером блокирования и монитором статуса для блокирования в NFS.

    Описатели файлов

    Одна из основ NFS реализуется описателями файлов. Для обращения к файлу или директории на сервере объекта используется opaque. Термин opaque обозначает, что сервер создает описатель файла, передает его обратно клиенту, который клиент затем использует при обращении к файлу. Клиент никогда не просматривает содержимое описателя файла - его содержимое представляет интерес только для сервера.

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

    Обычно пользовательский процесс не работает с описателями файлов. Обмен описателями файлов осуществляют NFS клиент и NFS сервер. В версии 2 NFS описатель файла занимает 32 байта, а в версии 3 он вырос до 64 байт.

    Unix серверы обычно хранят в описателе файла следующую информацию: идентификатор файловой системы (major и minor номера устройства файловой системы), номер инода (i-node) (уникальный номер внутри файловой системы), номер поколения инода (номер, который изменяется каждый раз, когда инод повторно используется для другого файла).

    Протокол монтирования

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

    На рисунке 29.5 описана последовательность действий Unix клиента при исполнении команды mount(8).

    Рисунок 29.5 Протокол монтирования, используемый Unix командой mount.

    При этом осуществляются следующие шаги.

    1. При загрузке сервера на нем стартует преобразователь портов.
    2. После преобразователя портов на сервере стартует демон монтирования ( mountd). Он создает конечную точку TCP и конечную точку UDP, а также назначает каждой из них динамически назначаемый номер порта. Затем он регистрирует эти номера у преобразователя портов.
    3. Клиент исполняется команду mount, которая выдает RPC вызов на преобразователь портов сервера, чтобы получить номер порта от демона монтирования на сервере. Для обмена между клиентом и преобразователем портов могут быть использованы и TCP и UDP, однако обычно используется UDP.
    4. Преобразователь портов сообщает номер порта.
    5. Команда mount выдает RPC вызов демону монтирования, чтобы смонтировать файловую систему сервера. И снова может быть использован как TCP, так и UDP, однако обычно используется UDP. Теперь сервер может проверить "годность" клиента основываясь на его IP адресе и номере порта, чтобы убедиться, можно ли этому клиенту смонтировать указанную файловую систему.
    6. Демон монтирования откликается описателем файла указанной файловой системы.
    7. Команда mount клиента выдает системный вызов mount, чтобы связать описатель файла, полученный в шаге 5, с локальной точкой монтирования на хосте клиента. Описатель файла хранится в коде NFS клиента, и с этого момента любое обращение пользовательских процессов к файлам на файловой системе сервера будет использовать описатель файла как стартовую точку.

    Подобная реализация отдает весь процесс монтирования, кроме системного вызова mount на клиенте, пользовательским процессам, а не ядру. Три программы, которые мы показали - команда mount, преобразователь портов и демон монтирования - пользовательские процессы.

    В этом примере на хосте sun (NFS клиент) была исполнена команда

    sun # mount -t nfs bsdi:/usr /nfs/bsdi/usr

    Эта команда монтирует директорию /usr на хосте bsdi (NFS сервер) как локальную файловую систему /nfs/bsdi/usr. На рисунке 29.6 показан результат.

    Рисунок 29.6 Монтирование директории bsdi:/usr как /nfs/bsdi/usr на хосте sun.

    После чего при обращении к файлу /nfs/bsdi/usr/rstevens/hello.c на клиенте sun, происходит обращение к файлу /usr/rstevens/hello.c на сервере bsdi.

    Процедуры NFS

    NFS сервер предоставляет 15 процедур, которые мы сейчас опишем. (Числа, которые использованные при описании, не совпадают с номерами NFS процедур, так как мы сгруппировали их по функциональному признаку.) Несмотря на то что NFS разрабатывалась таким образом, чтобы работать между различными операционными системами, а не только между Unix системами, некоторые из процедур основаны именно на Unix функционировании, что, в свою очередь, может не поддерживаться другими операционными системами (например, жесткие линки, символические линки, групповое пользование, права доступа на исполнение и так далее). Глава 4 содержит дополнительную информацию о характеристиках файловых систем, некоторыми из которых пользуется NFS.

    1. GETATTR. Возвращает атрибуты файлов: тип файла (обычный файл, директория и так далее), права доступа, размер файла, владельца файла, время последнего обращения и так далее.
    2. SETATTR. Устанавливает атрибуты файла. Установлен может быть только определенный набор атрибутов: права доступа, владелец, групповое владение, размер, время последнего обращения и время последней модификации.
    3. STATFS. Возвращает статус файловой системы: размер свободного пространства, оптимальный размер для передачи и так далее. Используется, например, Unix командой df.
    4. LOOKUP. "Оценивает" файл. Эта процедура вызывается клиентом каждый раз, когда пользовательский процесс открывает файл, который находится на NFS сервере. Возвращается описатель файла, вместе с атрибутами файла.
    5. READ. Читает из файла. Клиент указывает описатель файла, начальное смещение в байтах и максимальное количество байтов, которое необходимо считать (до 8192).
    6. WRITE. Записывает в файл. Клиент указывает описатель файла, начальное смещение в байтах, количество байт, которое необходимо записать, и данные, которые необходимо записать.

      Требуется, чтобы NFS записи были синхронными (с ожиданием). Сервер не может ответить OK до тех пор, пока данные не были успешно записаны (и любая другая информация о файле, которая должна быть обновлена) на диск.

    7. CREATE. Создает файл.
    8. REMOVE. Удаляет файл.
    9. RENAME. Переименовывает файл.
    10. LINK. Делает жесткий линк на файл. Жесткий линк это Unix концепция, которая определяет, что конкретный файл на диске может иметь любое количество точек входа (имен, которые также называются жесткими линками), которые указывают на этот файл.
    11. SYMLINK. Создает символический линк на файл. Символический линк это файл, который содержит имя другого файла. Большинство операций, которые осуществляются над символическим линком (например, открытие), в действительности совершаются с тем файлом, на котороый указывает символический линк.
    12. READLINK. Чтение символического линка возвращает имя файла, на который указывает символический линк.
    13. MKDIR. Создает директорию.
    14. RMDIR. Удаляет директорию.
    15. READDIR. Читает директорию. Используется, например, Unix командой ls.

    В действительности, приведенные имена процедур начинаются с префикса NFSPROC_, который мы опустили.

    UDP или TCP?

    NFS был исходно написан, чтобы использовать UDP, и эту возможность предоставляют все производители. Однако, более новые реализации, также поддерживают TCP. Поддержка TCP используется для работы в глобальных сетях, которые становится все быстрее. Поэтому использование NFS в настоящее время уже не ограничено локальными сетями.

    Границы между локальными и глобальными сетями стираются, и все это происходит очень быстро. Времена возврата меняются в очень широком диапазоне, и все чаще возникает переполнение. Эти характеристики глобальных сетей приводят к тому, что все чаще в них используются алгоритмы, которые мы рассматривали для TCP - медленный старт и избежание переполнения. Так как UDP не предоставляет ничего похожего на эти алгоритмы, то они или им подобные должны быть встроены в NFS клиент и сервер, иначе необходимо использовать TCP.

    NFS поверх TCP

    Реализация NFS Berkeley Net/2 поддерживает как UDP, так и TCP. [ Macklem 1991] описывает эту реализацию. Давайте рассмотрим, чем отличается использование NFS при работе поверх TCP.

    1. Когда сервер загружается, он запускает NFS сервер, который осуществляет активное открытие на TCP порт 2049, ожидая прихода запроса на соединение от клиента. Это обычно делается в дополнение к обычному NFS UDP, который ожидает входящие датаграммы на UDP порте 2049.
    2. Когда клиент монтирует файловую систему сервера с использованием TCP, он осуществляет активное открытие на TCP порт 2049 на сервере. При этом устанавливается TCP соединение между клиентом и сервером для этой файловой системы. Если тот же самый клиент монтирует еще одну файловую систему на том же самом сервере, создается еще одно TCP соединение.
    3. И клиент, и сервер устанавливают TCP опцию "оставайся в живых" на своих концах соединения (глава 23). Это позволяет определить момент выхода из строя или перезагрузки того или иного участника обмена.
    4. Все приложения на клиенте, которые используют файловую систему сервера, делят одно и то же TCP соединение для этой файловой системы. Например, если была на рисунке 29.6, бы еще одна директория на bsdi, с именем smith, ниже директории /usr, обращения к файлам в /nfs/bsdi/usr/rstevens и /nfs/bsdi/usr/smith делили бы одно и то же TCP соединение.
    5. Если клиент определяет, что сервер вышел из строя или перезагрузился (после получения TCP ошибки "соединение закрыто по тайм-ауту" или "соединение закрыто хостом"), он старается повторно подсоединиться к серверу. Клиент осуществляет еще одно активное открытие, чтобы повторно установить TCP соединение для этой файловой системы. Любой запрос от клиента, для которого отработан тайм-аут на предыдущем соединении, повторно выдается на новое соединение.
    6. Если клиент вышел из строя, то же происходит и с приложениями, которые работали до выхода из строя. Когда клиент перезагружается, он, возможно, повторно смонтирует файловую систему сервера с использованием TCP, причем будет использовано другое TCP соединение с сервером. Предыдущее соединение между клиентом и сервером для этой файловой системы находится в полуоткрытом состоянии (сервер думает, что оно все еще открыто), однако так как сервер установил опцию "оставайся в живых", это полуоткрытое соединение будет закрыто, когда TCP сервер пошлет следующую пробу "оставайся в живых".

    Со временем и другие производители планируют начать поддержку NFS поверх TCP.

    Примеры NFS

    Давайте воспользуемся tcpdump, чтобы посмотреть, какие NFS процедуры привлекаются клиентом для обычных операций с файлом. Когда tcpdump определяет, что UDP датаграмма содержит RPC вызов (call равен 0 на рисунке 29.1) с портом назначения 2049, он декодирует датаграмму как NFS запрос. Точно так же, если UDP датаграмма содержит RPC отклик (reply равен 1 на рисунке 29.2) с портом источника равным 2049, он декодирует датаграмму как NFS отклик.

    Простой пример: чтение файла

    В первом примере мы скопируем файл, находиться на NFS сервере, на терминал с использованием команды cat(1):

    Sun % cat /nfs/bsdi/usr/rstevens/hello.c копирование файла на терминал
    main()
    {
    printf ("hello, world\n");
    }

    Файловая система /nfs/bsdi/usr на хосте sun (NFS клиент) в действительности является файловой системой /usr на хосте bsdi (NFS сервер), как показано на рисунке 29.6. Ядро sun определяет это, когда cat открывает файл и использует NFS для доступа к файлу. На рисунке 29.7 показан вывод команды tcpdump.

    1 0.0 sun.7aa6 > bsdi.nfs: 104 getattr
    2 0.003587 (0.0036) bsdi.nfs > sun.7aa6: reply ok 96

    3 0.005390 (0.0018) sun.7aa7 > bsdi.nfs: 116 lookup "rstevens"
    4 0.009570 (0.0042) bsdi.nfs > sun.7aa7: reply ok 128

    5 0.011413 (0.0018) sun.7aa8 > bsdi.nfs: 116 lookup "hello.c"
    6 0.015512 (0.0041) bsdi.nfs > sun.7aa8: reply ok 128

    7 0.018843 (0.0033) sun.7aa9 > bsdi.nfs: 104 getattr
    8 0.022377 (0.0035) bsdi.nfs > sun.7aa9: reply ok 96

    9 0.027621 (0.0052) sun.7aaa > bsdi.nfs: 116 read 1024 bytes @ 0
    10 0.032170 (0.0045) bsdi.nfs > sun.7aaa: reply ok 140

    Рисунок 29.7 Функционирование NFS при чтении файла.

    Команда tcpdump декодирует NFS запрос или отклик, также она печатает поле XID для клиента, вместо номера порта. Поле XID в строках 1 и 2 равно 0x7aa6.

    Имя файла /nfs/bsdi/usr/rstevens/hello.c обрабатывается функцией открытия в ядре клиента по одному элементу имени за раз. Когда функция открытия достигает /nfs/bsdi/usr, она определяет, что это точка монтирования файловой системы NFS.

    В строке 1 клиент вызывает процедуру GETATTR, чтобы получить атрибуты директории сервера, которую смонтировал клиент (/usr). Этот RPC запрос содержит 104 байта данных, помимо IP и UDP заголовков. Отклик в строке 2 возвращает OK и содержит 96 байт данных, помимо IP и UDP заголовков. Мы видим на этом рисунке, что минимальное NFS сообщение содержит примерно 100 байт данных.

    В строке 3 клиент вызывает процедуру LOOKUP для файла rstevens и получает отклик OK в строке 4. LOOKUP указывает имя файла rstevens и описатель файла, который был сохранен ядром, когда монтировалась удаленная файловая система. Отклик содержит новый описатель файла, который используется в следующем шаге.

    В строке 5 клиент осуществляет LOOKUP файла hello.c с использованием описателя файла из строки 4. Он получает другой описатель файла в строке 6. Этот новый описатель файла как раз то, что клиент использует в строках 7 и 9, чтобы обратиться к файлу /nfs/bsdi/usr/rstevens/hello.c. Мы видим, что клиент осуществляет LOOKUP для каждого компонента имени в пути к открываемому файлу.

    В строке 7 клиент еще раз исполняет GETATTR, затем следует READ в строке 9. Клиент запрашивает 1024 байта, начиная со смещения равного 0, однако получает данных меньше чем 1024 байта. (После вычитания размеров RPC полей и других значений, возвращенных процедурой READ, в строке 10 возвращаются 38 байт данных. Это как раз размер файла hello.c.)

    В этом примере пользовательский процесс ничего не знает об этих NFS запросах и откликах, которые осуществляются ядром. Приложение всего лишь вызывает функцию открытия ядра, которая вызывает обмен 3 запросами и 3 откликами (строки 1-6), а затем вызывает функцию чтение ядра, которая вызывает 2 запроса и 2 отклика (строки 7-10). Для приложения клиента, файл, находящийся на NFS сервере, прозрачен.

    Простой пример: создание директории

    В качестве еще одного примера сменим рабочую директорию на директорию, которая находится на NFS сервере, а затем создадим новую директорию:

    Sun % cd /nfs/bsdi/usr/rstevens меняем рабочую директорию
    sun % mkdir Mail создаем директорию

    На рисунке 29.8 показан вывод команды tcpdump.

    1 0.0 sun.7ad2 > bsdi.nfs: 104 getattr
    2 0.004912 (0.0049) bsdi.nfs > sun.7ad2: reply ok 96

    3 0.007266 (0.0024) sun.7ad3 > bsdi.nfs: 104 getattr
    4 0.010846 (0.0036) bsdi.nfs > sun.7ad3: reply ok 96

    5 35.769875 (35.7590) sun.7ad4 > bsdi.nfs: 104 getattr
    6 35.773432 (0.0036) bsdi.nfs > sun.7ad4: reply ok 96

    7 35.775236 (0.0018) sun.7ad5 > bsdi.nfs: 112 lookup "Mail"
    8 35.780914 (0.0057) bsdi.nfs > sun.7ad5: reply ok 28

    9 35.782339 (0.0014) sun.7ad6 > bsdi.nfs: 144 mkdir "Mail"
    10 35.992354 (0.2100) bsdi.nfs > sun.7ad6: reply ok 128

    Рисунок 29.8 Функционирование NFS при смене директории (cd) на NFS директорию, а затем создание директории (mkdir).

    При смене директории клиент вызывает процедуру GETATTR дважды (строки 1-4). Когда мы создаем новую директорию, клиент вызывает процедуру GETATTR (строки 5 и 6), затем LOOKUP (строки 7 и 8, чтобы проверить, что такой директории не существует), затем MKDIR, чтобы создать директорию (строки 9 и 10). Отклик OK в строке 8 не означает, что директория существует. Он просто означает, что процедура вернула какое-то значение. tcpdump не интерпретирует значение, возвращаемое NFS процедурами. Команда просто печатает OK и количество байт данных в отклике.

    Безразличность

    Одна из характеристик NFS (критики NFS называют это бородавкой, а не характеристикой) заключается в том, что NFS сервер безразличен. Сервер не заботится о том, какие клиенты получают доступ и к каким файлам. Заметьте, что в списке NFS процедур, показанных ранее, нет процедуры открытия или закрытия. Процедура LOOKUP напоминает открытие, однако сервер никогда не знает, осуществил ли клиент обращение к файлу, после того как был сделан LOOKUP.

    Причина такого "безразличного поведения" заключается в том, чтобы упростить восстановление после выхода из строя сервера, после того как он сломался и перезагрузился.

    Пример: выход сервера из строя

    В следующем примере мы читаем файл с NFS сервера, когда сервер выходит из строя и перезагружается. Это покажет как "безразличность" сервера позволяет, клиенту "не знать" о том, что сервер вышел из строя. Все то время, пока сервер сломался и перезагружается, клиент не знает о проблеме, и приложение клиента работает так же, как и раньше.

    На клиенте sun мы стартовали cat с очень большим файлом в качестве аргумента (/usr/share/lib/termcap на NFS сервере svr4), отсоединили Ethernet кабель в процессе передачи, выключили и перезагрузили сервер и затем снова подсоединили кабель. Клиент был сконфигурирован таким образом, чтобы читать 1024 байта за одно NFS чтение. На рисунке 29.9 показан вывод tcpdump.

    Строки 1-10 соответствуют открытию файла клиентом. Эта операция напоминает ту, что показана на рисунке 29.7. В строке 11 мы видим первое чтение (READ) из файла 1024-х байт данных; отклик возвратился в строке 12. Это продолжается до строки 129 (чтение READ по 1024 байта и затем отклик OK).

    В строках 130 и 131 мы видим два запроса, которые отработаны по тайм-ауту и повторно переданы в строках 132 и 133. Первый вопрос: мы видим два запроса на чтение, один начинается со смещения 65536, а другой начинается со смещения 73728, почему? Ядро клиента определило, что приложение клиента осуществляет последовательное считывание, и постаралось получить блоки данных заранее. (Большинство Unix ядер осуществляют это чтение вперед (read-ahead).) Ядро клиента также запустило несколько NFS демонов блочного ввода-вывода (I/O) (biod процессы), которые стараются сгенерировать несколько RPC запросов от имени клиента. Один демон считывает 8192 байта, начиная с 65536 (в 1024-байтных цепочках), а другие осуществляют чтение вперед по 8192 байта, начиная с 73728.

    Повторные передачи клиента появляются в строках 130-168. В строке 169 мы видим, что сервер перезагрузился, и послал ARP запрос перед тем, как откликнуться на NFS запрос клиента из строки 168. Отклик на строку 168 посылается в строке 171. Запросы клиента на чтение (READ) продолжаются.

    1 0.0 sun.7ade > svr4.nfs: 104 getattr
    2 0.007653 (0.0077) svr4.nfs > sun.7ade: reply ok 96

    3 0.009041 (0.0014) sun.7adf > svr4.nfs: 116 lookup "share"
    4 0.017237 (0.0082) svr4.nfs > sun.7adf: reply ok 128

    5 0.018518 (0.0013) sun.7ae0 > svr4.nfs: 112 lookup "lib"
    6 0.026802 (0.0083) svr4.nfs > sun.7ae0: reply ok 128

    7 0.028096 (0.0013) sun.7ae1 > svr4.nfs: 116 lookup "termcap"
    8 0.036434 (0.0083) svr4.nfs > sun.7ae1: reply ok 128

    9 0.038060 (0.0016) sun.7ae2 > svr4.nfs: 104 getattr
    10 0.045821 (0.0078) svr4.nfs > sun.7ae2: reply ok 96

    11 0.050984 (0.0052) sun.7ae3 > svr4.nfs: 116 read 1024 bytes @ 0
    12 0.084995 (0.0340) svr4.nfs > sun.7ae3: reply ok 1124

    Считывание

    128 3.430313 (0.0013) sun.7b22 > svr4.nfs: 116 read 1024 bytes @ 64512
    129 3.441828 (0.0115) svr4.nfs > sun.7b22: reply ok 1124

    130 4.125031 (0.6832) sun.7b23 >
    131 4.868593 (0.7436) sun.7b24 >

    132 4.993021 (0.1244) sun.7b23 > svr4.nfs: 116 read 1024 bytes @ 65536
    133 5.732217 (0.7392) sun.7b24 > svr4.nfs: 116 read 1024 bytes @ 73728

    134 6.732084 (0.9999) sun.7b23 > svr4.nfs: 116 read 1024 bytes @ 65536
    135 7.472098 (0.7400) sun.7b24 > svr4.nfs: 116 read 1024 bytes @ 73728

    136 10.211964 (2.7399) sun.7b23 >
    137 10.951960 (0.7400) sun.7b24 >

    138 17.171767 (6.2198) sun.7b23 > svr4.nfs: 116 read 1024 bytes @ 65536
    139 17.911762 (0.7400) sun.7b24 > svr4.nfs: 116 read 1024 bytes @ 73728

    140 31.092136 (13.1804) sun.7b23 > svr4.nfs: 116 read 1024 bytes @ 65536
    141 31.831432 (0.7393) sun.7b24 > svr4.nfs: 116 read 1024 bytes @ 73728

    142 51.090854 (19.2594) sun.7b23 > svr4.nfs: 116 read 1024 bytes @ 65536
    143 51.830939 (0.7401) sun.7b24 > svr4.nfs: 116 read 1024 bytes @ 73728

    144 71.090305 (19.2594) sun.7b23 > svr4.nfs: 116 read 1024 bytes @ 65536
    145 71.830155 (0.7398) sun.7b24 > svr4.nfs: 116 read 1024 bytes @ 73728

    Повторные передачи

    167 291.824285 (0.7400) sun.7b24 > svr4.nfs: 116 read 1024 bytes @ 73728
    168 311.083676 (19.2594) sun.7b23 > svr4.nfs: 116 read 1024 bytes @ 65536

    Сервер перезагрузился

    169 311.149476 (0.0658) arp who-has sun tell svr4
    170 311.150004 (0.0005) arp reply sun is-at 8:0:20:3:f6:42

    171 311.154852 (0.0048) svr4.nfs > sun.7b23: reply ok 1124

    172 311.156671 (0.0018) sun.7b25 > svr4.nfs: 116 read 1024 bytes @ 66560
    173 311.168926 (0.0123) svr4.nfs > sun.7b25: reply ok 1124
    считывание

    Рисунок 29.9 Считывание файла клиентом, когда NFS сервер вышел из строя и перезагрузился.

    Приложение клиента никогда не узнает, что сервер выходил из строя и перезагружался, за исключением того, что между строками 129 и 171 была 5-минутная пауза, таким образом, выход из строя сервера прозрачен для клиента.

    Чтобы оценить продолжительность тайм-аутов при повторных передачах в этом примере, представьте, что существуют два демона клиента, каждый со своими собственными тайм-аутами. Интервалы для первого демона (читающего со смещения 65536) примерно следующие (округлено до двух знаков после запятой): 0,68; 0,87; 1,74; 3,48; 6,96; 13,92; 20,0; 20,0; 20,0 и так далее. Интервалы для второго демона (читающего со смещения 73728) точно такие же. Это означает, что эти NFS клиенты используют тайм-ауты, которые кратны 0,875 секунды с верхним пределом равным 20 секундам. После каждого тайм-аута интервал повторной передачи удваивается: 0,875; 1,75; 3,5; 7,0 и 14,0.

    Сколько времени клиент будет осуществлять повторные передачи? Клиент имеет две опции, которые могут повлиять на это. Во-первых, если файловая система сервера смонтирована жестко (hard) , клиент будет повторно передавать вечно, однако если файловая система сервера смонтирована мягко (soft) , клиент прекратит свои попытки после фиксированного количества повторных передач. Также, в случае жесткого монтирования клиент имеет опцию, позволяющую пользователю прервать неудачные повторные передачи или не прерывать. Если при монтировании файловой системы сервера, хост клиента указывает что прервать можно, и если мы не хотим ждать 5 минут, пока сервер перезагрузится после выхода из строя, мы можем ввести символ прерывания, чтобы прекратить работу приложения клиента.

    Несколько одинаковых процедур

    RPC процедуры могут быть исполнены сервером несколько раз, но при этом все равно возвращают тот же самый результат. Например, процедура чтения NFS. Как мы видели на рисунке 29.9, клиент просто повторно выдает вызов READ до тех пор, пока он получает отклик. В нашем примере причина повторной передачи была в том, что сервер вышел из строя. Если сервер не вышел из строя, а сообщения, содержащие RPC отклики, были потеряны (так как UDP ненадежный протокол), клиент просто повторно передает, и сервер снова осуществляет то же самое чтение (READ). Та же самая часть того же самого файла считывается снова и посылается клиенту.

    Это работает, потому что каждый запрос на чтение READ содержит начальное смещение. Если бы NFS процедура попросила сервер считать следующие N байт файла, это бы не сработало. Если бы сервер не был безразличным (это значение наоборот к безразличности), и отклик потерян, а клиент повторно выдает READ для следующих N байт, результат будет отличаться. Именно поэтому процедуры NFS READ и WRITE имеют начальное смещение. Именно клиент поддерживает состояние (текущее смещение для каждого файла), а не сервер.

    К несчастью, не все операции с файловыми системами можно исполнить несколько раз. Например, представьте себе следующие шаги: клиент NFS выдает запрос REMOVE, чтобы удалить файл; NFS сервер удаляет файл и отвечает OK; отклик сервера потерян; NFS клиент отрабатывает тайм-аут и повторно передает запрос; NFS сервер не может найти файл и возвращает ошибку; приложение клиента получает ошибку, сообщающую о том, что файл не существует. Эта ошибка возвращается приложению клиента, и эта ошибка несет неверную информацию - файл не существовал и был удален.

    Ниже приведен список NFS процедур, которые можно исполнить несколько раз: GETATTR, STATFS, LOOKUP, READ, WRITE, READLINK и READDIR. Процедуры, которые нельзя исполнить несколько раз: CREATE, REMOVE, RENAME, LINK, SYMLINK, MKDIR и RMDIR. SETATTR обычно исполняется несколько раз, если только она не была использована для того, чтобы обрезать файл.

    Так как в случае использования UDP всегда могут появиться потерянные отклики, NFS сервера должны иметь способ обработать операции, которые нельзя исполнять несколько раз. Большинство серверов имеют кэш последних откликов, в котором они хранят последние принятые отклики для подобных операций. Каждый раз, когда сервер получает запрос, он, во-первых, просматривает свой кэш, и если найдено совпадение, возвращает предыдущий отклик, вместо того чтобы вызывать NFS процедуру снова. [ Juszczak 1989] описывает детали этих типов кэша.

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

    NFS версии 3

    В течение 1994 года были выпущены спецификации для версии 3 протокола NFS [ Sun Microsystems 1993]. Реализации, как ожидается, станут доступными в течение 1994 года.

    Здесь вкратце описаны основные различия между версиями 2 и 3. Мы будем называть их V2 и V3.

    1. Описатели файлов в V2 это массив фиксированного размера - 32 байта. В V3 это массив переменного размера с размером до 64 байт. Массив переменной длины в XDR определяется 4-байтным счетчиком, за которым следуют реальные байты. Это уменьшает размер описателя файла в таких реализациях, как, например, Unix, где требуется всего около 12 байт, однако позволяет не-Unix реализациям обмениваться дополнительной информацией.
    2. V2 ограничивает количество байт на процедуры READ или WRITE RPC размером 8192 байта. Это ограничение не действует в V3, что, в свою очередь, означает, что с использованием UDP ограничение будет только в размере IP датаграммы (65535 байт). Это позволяет использовать большие пакеты при чтении и записи в быстрых сетях.
    3. Размеры файлов и начальное смещение байтов для процедур READ и WRITE расширены с 32 до 64 бит, что позволяет работать с файлами большего размера.
    4. Атрибуты файла возвращаются в каждом вызове, который может повлиять на атрибуты. Это уменьшает количество вызовов GETATTR, требуемых клиентом.
    5. Записи (WRITE) могут быть асинхронными, тогда как в V2 они должны были быть синхронными. Это может улучшить производительность процедуры WRITE.
    6. Одна процедура была удалена (STATFS) и семь были добавлены: ACCESS (проверка прав доступа к файлу), MKNOD (создание специального файла Unix), READDIRPLUS (возвращает имена файлов в директории вместе с их атрибутами), FSINFO (возвращает статистическую информацию о файловой системе), FSSTAT (возвращает динамическую информацию о файловой системе), PATHCONF (возвращает POSIX.1 информацию о файле) и COMMIT (передает ранее сделанные асинхронные записи на постоянное хранение).

    Краткие выводы

    RPC это способ построить приложение клиент-сервер таким образом, что клиент просто вызывает процедуры на сервере. Все сетевые детали спрятаны в stubах клиента и сервера, которые генерируются для приложений пакетом RPC и в подпрограммах библиотеки RPC. Мы показали формат RPC сообщений вызова и отклика и упомянули, что XDR используется, чтобы кодировать значения, что позволяет RPC клиентам и серверам работать на машинах с различной архитектурой.

    Одно из наиболее широко используемых приложений RPC это Sun NFS, протокол доступа к разнородным файлам, который широко используется на хостах практически всех размеров. Мы рассмотрели NFS и то, как он использует UDP или TCP. В протоколе NFS версии 2 (NFS Version 2) определено 15 процедур.

    Доступ клиента к NFS серверу начинается с протокола монтирования, после чего клиенту возвращается описатель файла. Затем клиент может получить доступ к файлам в файловой системе сервера с использованием этого описателя файла. Имена файлов просматриваются на сервере по одному элементу имени за раз, при этом для каждого элемента возвращается новый описатель файла. Конечный результат это описатель того файла, к которому было осуществлено обращение, и который используется при последовательных чтениях и записях.

    NFS старается сделать все свои процедуры независимыми от количества исполнений таким образом, чтобы клиент мог просто повторно выдать запрос, если отклик был потерян. Мы видели примеры этого: в случае, когда клиент читал файл, пока сервер вышел из строя и перезагружался.

    Упражнения

    На рисунке 29.7 мы видели, что tcpdump интерпретирует пакеты как NFS запросы и отклики, и при этом печатает XID. Может ли tcpdump сделать это для любых RPC запросов или откликов?
  • Как Вы думаете, почему в Unix системах программа RPC сервера использует динамически назначаемые порты, а не заранее известные?
  • RPC клиент вызвал две процедуры сервера. Первая процедура потребовалось на исполнение 5 секунд, а второй - 1 секунда. Клиент имеет тайм-аут равный 4 секундам. Нарисуйте временную диаграмму того, чем обмениваются клиент и сервер. (Представьте, что на прохождение сообщения от клиента к серверу и наоборот время не тратится.)
  • Что произойдет в примере на рисунке 29.9, если пока NFS сервер был выключен, его Ethernet плата была удалена?
  • Когда сервер перезагрузился на рисунке 29.9, он обрабатывал запрос, начинающийся на смещении 65536 (строки 168 и 171), а затем обрабатывал следующий запрос, начинающийся со смещения 66560 (строки 172 и 173). Что произойдет с запросом, начинающимся со смещением 73728 (строка 167)?
  • Когда мы описывали независимые от количества исполнений NFS процедуры, то показали пример отклика REMOVE, который потерялся в сети. Что произойдет в этом случае, если используется TCP вместо UDP?
  • Если NFS сервер использует динамически назначаемый порт вместо порта 2049, что произойдет с NFS клиентом, когда сервер выйдет из строя и перезагрузится?
  • Номеров зарезервированных портов (глава 1, раздел "Номера портов") очень-очень мало, их максимум 1023 на хост. Если NFS сервер требует, чтобы его клиенты имели зарезервированные порты (что обычно так и есть), и NFS клиент, использующий TCP, монтирует N файловых систем на N различных серверах, необходимо ли клиенту иметь различные зарезервированные номера портов для каждого соединения?
  • Каждый знает, что в UNIX-системах файловая система логически представляет собой набор физических файловых систем, подключенных к одной точке. Одна из самых основных прелестей такой организации, на мой взгляд, состоит в возможности динамически модифицировать структуру существующей файловой системы. Также, благодаря усилиям разработчиков, мы на сегодняшний день имеем возможность подключить ФС практически любого типа и любым удобным способом. Говоря «способом», я прежде всего хочу подчеркнуть возможность работы ядра ОС с файловыми системами посредством сетевых соединений.

    Множество сетевых протоколов предоставляют нам возможность работы с удаленными файлами, будь то FTP, SMB, Telnet или SSH. Благодаря способности ядра, в конечном итоге, не зависеть от типа подключаемой ФС, мы имеем возможность при помощи программы mount подключать что угодно и как угодно.

    Сегодня мне хочется рассказать об NFS — Network File System. Эта технология позволяет подключать отдельные точки ФС на удаленном компьютере к файловой системе локального компьютера. Сам протокол NFS позволяет выполнять операции с файлами достаточно быстро, безопасно и надежно. А что нам еще нужно? :-)

    Что необходимо для того, чтобы это работало

    Чтобы долго не разглагольствовать на тему версий NFS и их поддержку в различных ядрах, сразу сделаем допущение, что версия вашего ядра не ниже 2.2.18. В официальной документации разработчики обещают полную поддержку функционала NFS версии 3 в этом ядре и более поздних версий.

    Установка

    Для запуска сервера NFS в моей Ubuntu 7.10 — the Gutsy Gibbon понадобилось установить пакеты nfs-common и nfs-kernel-server. Если же нужен только клиент NFS, то nfs-kernel-server устанавливать не нужно.

    Настройка сервера

    После того, как все пакеты успешно установлены, необходимо проверить, запущен ли демон NFS:

    /etc/init.d/nfs-kernel-server status

    Если демон не запущен, его нужно запустить командой

    /etc/init.d/nfs-kernel-server start

    После того, как все успешно запустилось, можно приступать к экспорту файловой системы. Сам процесс очень прост и занимает минимум времени.

    Основной файл конфигурации NFS-сервера располагается в /etc/exports и имеет следующий формат:

    Directory machine1(option11,option12) machine2(option21,option22)

    directory — абсолютный путь к каталогу ФС сервера, к которому нужно дать доступ

    machineX — DNS-имя или IP-адрес клиентского компьютера, с которого разрешается доступ

    optionXX — параметры экспорта ФС, наиболее часто используемые из них:

    • ro — доступ к файлам разрешается только для чтения
    • rw — доступ предоставляется на чтение/запись
    • no_root_squash — по умолчанию, если вы подключаетесь к ресурсу NFS от имени root, сервер, безопасности ради, на своей стороне будет обращаться к файлам от имени пользователя nobody. Однако, если включить эту опцию, то обращение к файлам на стороне сервера будет будет производиться от имени root. Аккуратней с этой опцией.
    • no_subtree_check — по умолчанию, если вы на сервере экспортируете не весь раздел, а только часть ФС, демон будет проверять, является ли запрошенный файл физически размещенным на том же разделе или нет. В случае, если вы экспортируете весь раздел или точка подключения экспортируемой ФС не затрагивает файлы с других физических томов, то можно включить эту опцию. Это даст вам увеличение скорости работы сервера.
    • sync — включайте эту опцию, если есть вероятность внезапного обрыва связи или отключения питания сервера. Если эта опция не включена, то очень повышается риск потери данных при внезапной остановке сервера NFS.

    Итак, допустим, нам нужно дать доступ компьютеру ashep-desktop к каталогу /var/backups компьютера ashep-laptop. Доступ к каталогу необходим для копирования резервных копий файлов с ashep-desktop. У меня файл получился следующим:

    /var/backups ashep-desktop(rw,no_subtree_check,sync)

    После добавления строки в /etc/exports необходимо перезапустить сервер NFS для вступления изменений в силу.

    /etc/init.d/nfs-kernel-server restart

    Вот и все. Можно приступать к подключению экспортированной ФС на клиентском компьютере.

    Настройка клиента

    На клиентской стороне удаленная файловая система монтируется так же, как и все остальные — командой mount. Также, никто не запрещает вам использовать /etc/fstab в случае, если подключать ФС нужно автоматически при загрузке ОС. Итак, вариант с mount будет выглядеть так:

    Mount -t nfs ashep-laptop:/var/backups/ /mnt/ashep-laptop/backups/

    Если все прошло успешно и вам необходимо выполнять подключение к удаленной ФС автоматически при загрузке — просто добавляем строку в /etc/fstab:

    Ashep-laptop:/var/backups /mnt/ashep-laptop/backups nfs auto 0 0

    Что еще

    Вот и получился практический, малюсенький обзор возможностей NFS. Конечно, это всего лишь малая часть того, что умеет NFS. Этого достаточно для использования дома или в небольшом офисе. Если же вам этого недостаточно, рекомендую в первую очередь прочесть