Файловая система NFS (Network File System) создана компанией Sun Microsystems. В настоящее время это стандартная сетевая файловая система для ОС семейства UNIX, кроме того, клиенты и серверы NFS реализованы для многих других ОС. Принципы ее организации на сегодня стандартизованы сообществом Интернета, последняя версия NFS v.4 описывается спецификацией RFC ЗОЮ, выпущенной в декабре 2000 года.
NFS представляет собой систему, поддерживающую схему удаленного доступа к файлам. Работа пользователя с удаленными файлами после выполнения операции монтирования становится полностью прозрачной - поддерево файловой системы сервера NFS становится поддеревом локальной файловой системы.
Одной из целей разработчиков NFS была поддержка неоднородных систем с клиентами и серверами, работающими под управлением различных ОС на различной аппаратной платформе. Этой цели способствует реализация NFS на основе механизма Sun RFC, поддерживающего по умолчанию средства XDR для унифицированного представления аргументов удаленных процедур.
Для обеспечения устойчивости клиентов к отказам серверов в NFS принят подход stateless, то есть серверы при работе с файлами не хранят данных об открытых клиентами файлах.
Основная идея NFS - позволить произвольной группе пользователей разделять общую файловую систему. Чаще всего все пользователи принадлежат одной локальной сети, но не обязательно. Можно выполнять NFS и на глобальной сети. Каждый NFS-сервер предоставляет один или более своих каталогов для доступа удаленным клиентам. Каталог объявляется достудным со всеми своими подкаталогами. Список каталогов, которые сервер передает, содержится в файле /etc/exports, так что эти каталоги экспортируются сразу автоматически при загрузке сервера. Клиенты получают доступ к экспортируемым каталогам путем монтирования. Многие рабочие станции Sun бездисковые, но и в этом случае можно монтировать удаленную файловую систему к корневому каталогу, при этом вся файловая система целиком располагается на сервере. Выполнение программ почти не зависит от того, где расположен файл: локально или на удаленном диске. Если два или более клиента одновременно смонтировали один и тот же каталог, то они могут связываться путем разделения файла.
В своей работе файловая система NFS использует два протокола.
Первый NFS-протокол управляет монтированием. Клиент посылает серверу полное имя каталога и запрашивает разрешение на монтирование этого каталога в какую-либо точку собственного дерева каталогов. При этом серверу не указывается, в какое место будет монтироваться каталог сервера. Получив имя, сервер проверяет законность этого запроса и возвращает клиенту дескриптор файла, являющегося удаленной точкой монтирования. Дескриптор включает описатель типа файловой системы, номер диска, номер индексного дескриптора (inode) каталога, который является удаленной точкой монтирования, информацию безопасности. Операции чтения и записи файлов из монтируемых файловых систем используют дескрипторы файлов вместо символьного имени.
Монтирование может выполняться автоматически, с помощью командных файлов при загрузке. Существует другой вариант автоматического монтирования: при загрузке ОС на рабочей станции удаленная файловая система не монтируется, но при первом открытии удаленного файла ОС посылает запросы каждому серверу и после обнаружения этого файла монтирует каталог того сервера, на котором расположен найденный файл.
Второй NFS-протокол используется для доступа к удаленным файлам и каталогам. Клиенты могут послать запрос серверу для выполнения какого-либо действия над каталогом или операции чтения или записи файла. Кроме того, они могут запросить атрибуты файла, такие как тип, размер, время создания и модификации. NFS поддерживается большая часть системных вызовов UNIX, за исключением open и close. Исключение open и close не случайно. Вместо операции открытия удаленного файла клиент посылает серверу сообщение, содержащее имя файла, с запросом отыскать его (lookup) и вернуть дескриптор файла. В отличие от вызова open вызов lookup не копирует никакой информации во внутренние системные таблицы. Вызов read содержит дескриптор того файла, который нужно читать, смещение в уже читаемом файле и количество байт, которые нужно прочитать. Преимуществом такой схемы является то, что сервер не запоминает ничего об открытых файлах. Таким образом, если сервер откажет, а затем будет восстановлен, информация об открытых файлах не потеряется, потому что она не поддерживается.
При отказе сервера клиент просто продолжает посылать на него команды чтения или записи в файлы, однако не получив ответа и исчерпав тайм-аут, клиент повторяет свои запросы. После перезагрузки сервер получает очередной повторный запрос клиента и отвечает на него. Таки образом, крах сервера вызывает только некоторую паузу в обслуживании клиентов, но никаких дополнительных действий по восстановлению соединений и повторному открытию файлов от клиентов не требуется.
К сожалению, NFS затрудняет блокировку файлов. Во многих ОС файл может быть открыт и заблокирован так, чтобы другие процессы не имели к нему доступа. Когда файл закрывается, блокировка снимается. В системах stateless, подобных NFS, блокирование не может быть связано с открытием файла, так как сервер не знает, какой файл открыт. Следовательно, NFS требует специальных дополнительных средств управления блокированием.
В NFS используется кэширование на стороне клиента, данные в кэш переносятся поблочно и применяется упреждающее чтение, при котором чтение блока в кэш по требованию приложения всегда сопровождается чтением следующего блока по инициативе системы. Метод кэширования NFS не сохраняет семантику UNIX для разделения файлов. Вместо этого используется не раз подвергавшаяся критике семантика, при которой изменения данных в кэшируемом клиентом файле видны другому клиенту, в зависимости от временных соотношений. Клиент при очередном открытии файла, имеющегося в его кэше, проверяет у сервера, когда файл был в последний раз модифицирован. Если это произошло после того, как файл был помещен в кэш, файл удаляется из кэша и от сервера получается новая копия файла. Клиенты распространяют модификации, сделанные в кэше, с периодом в 30 секунд, так что сервер может получить обновления с большой задержкой. В результате работы механизмов удаления данных из кэша и распространения модификаций данные, получаемые каким-либо клиентом, не всегда, являются самыми свежими.
Репликация в NFS не поддерживается.
Служба каталогов
Назначение и принципы организации
Подобно большой организации, большая компьютерная сеть нуждается в централизованном хранении как можно более полной справочной информации о самой себе. Решение многих задач в сети опирается на информацию о пользователях сети - их именах, используемых для логического входа в систему, паролях, правах доступа к ресурсам сети, а также о ресурсах и компонентах сети: серверах, клиентских компьютерах, маршрутизаторах, шлюзах, томах файловых систем, принтерах и т. п.
Приведем примеры наиболее важных задач, требующих наличия в сети централизованной базы справочной информации:
Такие примеры можно продолжать, но нетрудно привести и контраргумент, заставляющий усомниться в необходимости использования в сети централизованной базы справочной информации - долгое время сети работали без единой справочной базы, а многие сети и сейчас работают без нее. Действительно, существует много частных решений, позволяющих достаточно эффективно организовать работу сети на основе частных баз справочной информации, которые могут быть представлены обычными текстовыми файлами или таблицами, хранящимися в теле приложения. Например, в ОС UNIX традиционно используется для хранения данных об именах и паролях пользователей файл passwd, который охватывает пользователей только одного компьютера. Имена адресатов электронной почты также можно хранить в локальном файле клиентского компьютера. И такие частные справочные системы неплохо работают - практика это подтверждает.
Однако это возражение справедливо только для сетей небольших и средних размеров, в крупных сетях отдельные локальные базы справочной информации теряют свою эффективность. Хорошим примером, подтверждающим неприменимость локальных решений для крупных сетей, является служба имен DNS, работающая в Интернете. Как только размеры Интернета превысили определенный предел, хранить информацию о соответствии имен и IP-адресов компьютеров сети в локальных текстовых файлах стало неэффективно. Потребовалось создать распределенную базу данных, поддерживаемую иерархически связанными серверами имен, и централизованную службу над этой базой, чтобы процедуры разрешения символьных имен в Интернете стали работать быстро и эффективно.
Для крупной сети неэффективным является также применение большого числа справочных служб узкого назначения: одной для аутентификации, другой - для управления сетью, третей - для разрешения имен компьютеров и т. д. Даже если каждая из таких служб хорошо организована и сочетает централизованный интерфейс с распределенной базой данных, большое число справочных служб приводит к дублированию больших объемов информации и усложняет администрирование и управление сетью. Например, в Windows NT имеется по крайней мере пять различных типов справочных баз данных. Главный справочник домена (NT Domain Directory Service) хранит информацию о пользователях, которая требуется при организации их логического входа в сеть. Данные о тех же пользователях могут содержаться и в другом справочнике, используемом электронной почтой Microsoft Mail. Еще три базы данных поддерживают разрешение адресов: WINS устанавливает соответствие Netbios-имен IP-адресам, справочник DNS (сервер имен домена) оказывается полезным при подключении NT-сети к Интернету, и наконец, справочник протокола DHCP используется для автоматического назначения IP-адресов компьютерам сети. Очевидно, что такое разнообразие справочных служб усложняет жизнь администратора и приводит к дополнительным ошибкам, когда учетные данные одного и того же пользователя нужно ввести в несколько баз данных. Поэтому в новой версии Windows 2000 большая часть справочной информации о системе может храниться службой Active Directory - единой централизованной справочной службой, использующей распределенную базу данных и интегрированной со службой имен DNS.
Результатом развития систем хранения справочной информации стало появление в сетевых операционных системах специальной службы - так называемой службы каталогов (Directory Services), называемой также справочной службой (directory - справочник, каталог). Служба каталогов хранит информацию обо всех пользователях и ресурсах сети в виде унифицированных объектов с определенными атрибутами, а также позволяет отражать взаимосвязи между хранимыми объектами, такие как принадлежность пользователей к определенной группе, права доступа пользователей к компьютерам, вхождение нескольких узлов в одну подсеть, коммуникационные связи между подсетями, производственную принадлежность серверов и т. д. Служба каталогов позволяет выполнять над хранимыми объектами набор некоторых базовых операций, таких как добавление и удаление объекта, включение объекта в другой объект, изменение значений атрибута объекта, чтение атрибутов и некоторые другие. Обычно над службой каталогов строятся различные специфические сетевые приложения, которые используют информацию службы для решения конкретных задач: управления сетью, аутентификации пользователей, обеспечения прозрачности служб и других, перечисленных выше. Служба каталогов обычно строится на основе модели клиент-сервер: серверы хранят базу справочной информации, которой пользуются клиенты, передавая серверам по сети соответствующие запросы. Для клиента службы каталогов она представляется единой централизованной системой, хотя большинство хороших служб каталогов имеют распределенную структуру, включающую большое количество серверов, но эта структура для клиентов прозрачна.
Важным вопросом является организация базы справочных данных. Единая база данных, хранящая справочную информацию большого объема, порождает все то же множество проблем, что и любая другая крупная база данных. Реализация справочной службы как локальной базы данных, хранящейся в виде одной копии на одном из серверов сети, не подходит для большой системы по нескольким причинам, и в первую очередь вследствие низкой производительности и низкой надежности такого решения. Производительность будет низкой из-за того, что запросы к базе от всех пользователей и приложений сети будут поступать на единственный сервер, который при большом количестве запросов обязательно перестанет справляться с их обработкой. То есть такое решение плохо масштабируется в отношении количества обслуживаемых пользователей и разделяемых ресурсов. Надежность также не может быть высокой в системе с единственной копией данных. Кроме снятия ограничений по производительности и надежности желательно, чтобы структура базы данных позволяла производить логическое группирование ресурсов и пользователей по структурным подразделениям предприятия и назначать для каждой такой группы своего администратора.
Проблемы сохранения производительности и надежности при увеличении масштаба сети обычно решаются за счет распределенных баз данных справочной информации. Разделение данных между несколькими серверами снижает нагрузку на каждый сервер, а надежность при этом достигается за счет наличия нескольких реплик каждой части базы данных. Для каждой части базы данных можно назначить своего администратора, который обладает правами доступа только к объектам своей порции информации обо всей системе. Для пользователя же (и для сетевых приложений) такая распределенная база данных представляется единой базой данных, которая обеспечивает доступ ко всем ресурсам сети вне зависимости от того, с какой рабочей станции поступил запрос.
Существуют два популярных стандарта для служб каталогов. Во-первых, это стандарт Х.500, разработанный ITU-T (во время разработки стандарта эта организация носила имя CCITT). Этот стандарт определяет функции, организацию справочной службы и протокол доступа к ней. Разработанный в первую очередь для использования вместе с почтовой службой Х.400 стандарт Х.500 позволяет эффективно организовать хранение любой справочной информации и служит хорошей основой для универсальной службы каталогов сети.
Другим стандартом является стандарт LDAP (Light-weight Directory Access Protocol), разработанный сообществом Интернета. Этот стандарт определяет упрощенный протокол доступа к службе каталогов, так как службы, построенные на основе стандарта Х.500, оказались чересчур громоздкими. Протокол LDAP получил широкое распространение и стал стандартом де-факто в качестве протокола доступа клиентов к ресурсам справочной службы.
Существует также несколько практических реализаций служб каталогов для сетевых ОС. Наибольшее распространение получила служба NDS компании Novell, разработанная в 1993 году для сетевой ОС NetWare 4.0, а сегодня реализованная также и для Windows NT/2000. Большой интерес вызывает служба каталогов Active Directory, разработанная компанией Microsoft для Windows 2000. Обе эти службы поддерживают протокол доступа LDAP и могут работать в очень крупных сетях благодаря своей распределенности.
Служба каталогов NDS
Служба NDS (NetWare Directory Services) - это глобальная справочная служба, опирающаяся на распределенную объектно-ориентированную базу данных сетевых ресурсов. База данных NDS содержит информацию обо всех сетевых ресурсах, включая информацию о пользователях, группах пользователей, принтерах, томах и компьютерах. ОС NetWare (а также другие клиенты NDS, работающие на других платформах) использует информацию NDS для обеспечения доступа к этим ресурсам.
База данных NDS заменила в свое время справочник bindery предыдущих версий NetWare. Справочник bindery - это «плоская», или одноуровневая база данных, разработанная для поддержки одного сервера. В ней также использовалось понятие «объект» для сетевого ресурса, но трактовка этого термина отличалась от общепринятой. Объекты bindery идентифицировались простыми числовыми значениями и имели определенные атрибуты. Однако для этих объектов не определялись явные взаимоотношения наследования классов объектов, поэтому взаимоотношения между объектами bindery устанавливались администратором произвольно, что часто приводило к нарушению целостности данных.
База данных службы NDS представляет собой многоуровневую базу данных, поддерживающую информацию о ресурсах всех серверов сети. Для совместимости с предыдущими версиями NetWare в службе NDS предусмотрен механизм эмуляции базы bindery.
Служба NDS - это значительный шаг вперед по сравнению с предыдущими версиями за счет:
Распределенность заключается в том, что информация не хранится на одном сервере, а разделена на части, называемые разделами (partitions). NetWare хранит эти разделы на нескольких серверах сети (рис. 10.8). Это свойство значительно упрощает администрирование и управление большой сетью, так как она представляется администратору единой системой. Кроме того, обеспечивается более быстрый доступ к базе данных сетевых ресурсов за счет обращения к ближайшему серверу.
Рис. 10.8. Разделы базы данных NDS
Реплика - это копия информации раздела NDS. Можно создать неограниченное количество реплик каждого раздела и хранить их на разных серверах. Если один сервер останавливается, то копии этой информации могут быть получены с другого сервера. Это увеличивает отказоустойчивость системы, так как ни один из серверов не отвечает за всю информацию базы данных NDS.
Прозрачность заключается в том, что NDS автоматически создает связи между программными и аппаратными компонентами, которые обеспечивают пользователю доступ к сетевым ресурсам. NDS при этом не требует от пользователя знаний физического расположения этих ресурсов. Задавая сетевой ресурс по имени, вы получите к нему корректный доступ даже в случае изменения его сетевого адреса или места расположения.
Глобальность NDS заключается в том, что после входа вы получаете доступ к ресурсам всей сети, а не только одного сервера, как было в предыдущих версиях. Это достигается за счет процедуры глобального логического входа (global login). Вместо входа в отдельный сервер пользователь NDS входит в сеть, после чего он получает доступ к разрешенным для него ресурсам сети. Информация, предоставляемая во время логического входа, используется для идентификации пользователя. Позже, при попытке пользователя получить доступ к ресурсам, таким как серверы, тома или принтеры, фоновый процесс идентификации проверяет, имеет ли пользователь право на данный ресурс.
Важнейший компонент любой распределенной системы - файловая система, которая в этом случае также является распределенной. Как и в централизованных системах, функцией файловой системы является хранение программ и данных и предоставление клиентам доступа к ним. Распределенная файловая система поддерживается одним или более компьютерами, хранящими файлы. Файловые серверы обычно содержат иерархические файловые системы, каждая из которых имеет корневой каталог и каталоги более низких уровней. Во многих сетевых файловых системах клиентский компьютер может подсоединять и монтировать эти файловые системы к своим локальным файловым системам, обеспечивая пользователю удобный доступ к удаленным каталогам и файлам. При этом данные монтируемых файлов никуда не перемещаются физически, оставаясь на серверах.
С программной точки зрения распределенная файловая система (ФС) - это сетевая служба, включающая программы-серверы и программы-клиенты, взаимодействующие между собой по определенному протоколу. Файловая служба в распределенных файловых системах имеет две функционально различные части: собственно файловую службу и службу каталогов файловой системы. Первая имеет дело с операциями над отдельными файлами, такими как чтение, запись или добавление (изменение), а вторая - с созданием каталогов и управлением ими, добавлением и удалением файлов из каталогов и т. п.
В хорошо организованной распределенной системе пользователи не знают, как реализована файловая система (сколько файловых серверов, где они расположены, как они работают). В идеале для пользователя сетевая файловая система должна выглядеть так, как его собственная на его компьютере, т. е. быть совершенно прозрачной. Однако в реальности сетевые файловые системы пока еще не полностью соответствуют такому идеалу.
Сетевая файловая система в общем случае включает следующие элементы :
Локальные файловые системы;
Интерфейсы локальной файловой системы;
Серверы сетевой файловой системы;
Клиенты сетевой файловой системы;
Интерфейсы сетевой файловой системы;
Протокол клиент-сервер сетевой файловой системы.
Клиенты сетевой ФС - это программы, работающие на многочисленных компьютерах, подключенных к сети. Эти программы обслуживают запросы приложений на доступ к файлам, хранящимся на удаленных компьютерах. Клиент сетевой ФС передает по сети запросы другому программному компоненту - серверу сетевой ФС, работающему на удаленном компьютере. Сервер, получив запрос, может выполнить его самостоятельно либо, что является более распространенным вариантом, передать запрос для обработки локальной файловой системе. После получения ответа от локальной ФС сервер передает его по сети__
Клиент и сервер сетевой ФС взаимодействуют друг с другом по сети по определенному протоколу. В случае совпадения интерфейсов локальной и сетевой ФС этот протокол может быть достаточно простым. Одним из механизмов, используемых для этой цели, может быть механизм RPC.
В операционных системах Windows основной сетевой файловой службы является протокол SMB (Server Message Block), который был совместно разработан компаниями Microsoft, Intel и IBM. Его последние расширенные версии получили название Common Internet File System, CIFS.
Протокол работает на прикладном уровне модели OSI. Для передачи по сети своих сообщений SMB использует различные транспортные протоколы. Исторически первым таким протоколом был NetBIOS (и его более поздняя версия NetBEUI), но сейчас сообщения SMB могут передаваться и с помощью других протоколов (TCP/UDP и IPX).
SMB относится к классу протоколов, ориентированных на соединение. Его работа начинается с того, что клиент отправляет серверу специальное сообщение с запросом на установление соединения. Если сервер готов к установлению соединения, он отвечает сообщением-подтверждением. После установления соединения клиент может обращаться к серверу, передавая ему в сообщениях SMB команды манипулирования файлами и каталогами. В процессе работы возможно возникновение ряда ситуаций, которые могут повлиять на эффективность удаленного доступа к файлам :
1. Отказ компьютера, на котором выполняется сервер сетевой файловой системы, во время сеанса связи с клиентом. Локальная ФС запоминает состояние последовательных операций, которые приложение выполняет с одним и тем же файлом, за счет ведения__ внутренней таблицы открытых файлов (системные вызовы open, read, write изменяют состояние этой таблицы). При крахе системы таблица открытых файлов теряется после перезагрузки серверного компьютера. В этом случае приложение, работаю-щее на клиентском компьютере, не может продолжить работу с файлами, открытыми до краха.
Одно из решений проблемы основано на передаче функции ведения и хранения таблицы открытых файлов от сервера клиенту. При такой организации протокол клиент-сервер упрощается, так как перезагрузка сервера приводит только к паузе в обслуживании.
2. Большие задержки в обслуживании из-за запросов в сети и перезагрузки файлового сервера при подключении большого числа клиентов. Решением проблемы может быть кэширование файлов (частично или целиком) на стороне клиента. Однако в этом случае протокол должен учитывать возможность образования нескольких копий одного и того же файла, которые могут независимо модифицироваться разными пользователями, т. е. протокол должен обеспечивать согласованность копий файлов, имеющихся на разных компьютерах.
3. Потери данных и разрушение целостности файловой системы при сбоях и отказах компьютеров, играющих роль файловых серверов. Для повышения отказоустойчивости сетевой ФС можно хранить несколько копий каждого файла (или целиком всей ФС) на нескольких серверах. Такие копии файла называются репликами (replica).
Репликация файлов не только повышает отказоустойчивость, но и решает проблему перегрузки файловых серверов, так как запросы к файлам распределяются между несколькими серверами, что повышает производительность файловой системы.
4. Аутентификация выполняется на одном компьютере, например на клиентском, а авторизация, т. е. проверка прав доступа к каталогам или файлам, - на другом, выполняющем роль файлового сервера. Эта общая проблема всех сетевых служб должна учитываться протоколом взаимодействия клиентов и серверов файловой службы.
Перечисленные проблемы решаются комплексно путем создания службы центра лизованной аутентификации, репликации, кэширования и др. Эти дополнительные службы находят свое отражение в протоколе взаимодействия клиентов и серверов, в результате чего создаются различные протоколы этого типа, поддерживающие тот или иной набор дополнительных функций. Поэтому для одной и той же локальной ФС могут существовать различные протоколы сетевой ФС (рис. 5.30). Так, к файловой системе NTFS сегодня можно получить доступ с помощью протоколов SMB, NCP (NetWare Control Protocol) и NFS (Network File System - протокол сетевой ФС компании Sun Microsystems, используемой в различных вариантах ОС семейства UNIX).
С другой стороны, с помощью одного и того же протокола может реализоваться удаленный доступ к локальным ФС разного типа. Например, протокол SMB используется для доступа не только к ФС типа FAT, но и ФС NTFS, HPFS (рис. 5.31). Эти ФС могут располагаться как на разных, так и на одном компьютере.__
Контрольные вопросы к главе 5
1. Какими преимуществами обладают сети по сравнению с раздельным использованием компьютеров?
2. Всегда ли совпадают физическая и логическая топологии сети?
3. Как классифицируются сети по величине охватываемой территории?
4. Какой компьютер может выполнять роль сервера в сети?
5. Что такое файловый сервер и сервер печати?
6. Какие функции выполняют регистрационные серверы?
7. Какие функции выполняют серверы удаленного доступа?
8. Что такое прокси-сервер?
9. Перечислите возможных клиентов компьютерной сети.
10. Что такое ≪толстый≫ и ≪тонкий≫ клиенты в компьютерной сети?
11. Как вы понимаете термин ≪сегментация≫ сети?
12. Что такое МАС-адрес?
13. Чем распределенная ОС отличается от сетевой? Существуют ли в настоящее время по-настоящему распределенные сетевые системы?
14. Перечислите основные компоненты сетевой ОС. Что такое сетевая служба? Какие сетевые службы вы можете назвать?
15. Часть сетевых служб направлена не на пользователя, а на администратора. Какие это службы?
16. Что представляли собой первые сетевые ОС? Какие подходы к созданию сетевых ОС используются в настоящее время?
17. Назовите характерные черты одноранговых сетей. В чем основная особенность многоранговой сети?
18. Что такое серверная ОС? Какие они бывают? Чем серверная ОС отличается от клиентской?
19. Сколько вариантов двухзвенных схем используется для распределенной обработки приложений?
20. Чем хороша двухзвенная обработка приложений при сотрудничестве сервера и клиента?
21. Есть ли преимущества у трехзвенной схемы обработки приложений, в чем они заключаются?
22. Как могут взаимодействовать процессы в распределенных системах?
23. Какие основные примитивы используются в транспортной системе сетевой ОС?
24. Как организуется синхронизация процессов в сети?
25. Что понимается под вызовом удаленных процедур?
На данный момент в вашем распоряжении должно быть работающее TCP/IP-подключение к вашей сети. Вы должны быть в состоянии пинговать другие компьютеры сети и, если вы соответствующим образом настроили шлюз, вы также должны быть в состоянии пинговать компьютеры в Интернете. Как известно, главной целью подключения компьютера к сети, является получение доступа к информации. Хотя некоторые люди могут подключать компьютер к сети просто так, большинство людей хотели бы предоставлять и получать доступ к файлам и принтерам. Они хотели бы получать доступ к документам в Интернете или играть в онлайновые игры. Установив в свою новую систему Slackware поддержку TCP/IP и необходимое программное обеспечение, вы всё это получите; однако, установив только поддержку TCP/IP, функциональность будет очень ограниченной. Чтобы предоставлять и получать общий доступ к файлам, нам потребуется переносить их туда и обратно, используя FTP или SCP. Мы не можем посматривать на нашем новой компьютере со Slackware дерево файлов через значки “Сетевое окружение” или “Вся сеть” с Windows-компьютеров. Мы хотели бы иметь возможность иметь постоянный доступ к файлам на других Unix-машинах.
В идеале мы хотели бы использовать сетевую файловую систему , позволяющую нам иметь прозрачный доступ к файлам на компьютерах. Программам, которые мы используем для работы с информацией, хранимой на компьютерах, на самом деле даже не надо знать на каком компьютере хранится нужный файл. Им нужно только знать, что этот файл существует, и способ для его получения. Дальнейшее уже является задачей операционной системы, обеспечивающей доступ к этому файлу с помощью доступных локальных и сетевых файловых систем. Две наиболее часто используемые сетевые файловые системы - это SMB (реализованная через Samba) и NFS.
SMB (Server Message Block, блок серверных сообщений) - это потомок более старого протокола NetBIOS, изначально разработанного в IBM для их продукта LAN Manager. Компанию Microsoft в свою очередь всегда интересовал NetBIOS и его наследники (NetBEUI, SMB и CIFS). Проект Samba начал своё существование в 1991 году, когда он был написан для обеспечения связи между IBM PC и сервером Unix. Сегодня предоставление общего доступа к файлам и службам печати через сеть SMB является предпочитаемым методом практически для всего цивилизованного мира, поскольку его поддерживает и Windows.
Конфигурационный файл Samba /etc/samba/smb.conf является одним из самых хорошо документированных конфигурационных файлов, которые вы сможете найти. К вашим услугам уже готовые примеры с настройками общих ресурсов, так что вы можете просмотреть и изменить их согласно своим потребностям. Если же вам нужен ещё больший контроль, к вашим услугам страница руководства smb.conf. Поскольку Samba имеет такую хорошую документацию, мы не будем её здесь переписывать. Однако быстро остановимся на основных моментах.
smb.conf разбит на несколько разделов: по одному разделу на общий ресурс плюс один глобальный раздел для настройки параметров, которые используются везде. Некоторые параметры являются действительными только в глобальном разделе, а некоторые верны только за его пределами. Помните, что глобальный раздел может быть переопределён любым другим разделом. За дополнительной информацией обращайтесь к страницам руководства.
Вы скорее всего захотите отредактировать свой файл smb.conf, чтобы отразить в нём параметры своей локальной сети. Советуем вам изменить перечисленные ниже пункты:
Это будет описание вашего компьютера Slackware, показываемое в папке Сетевое окружение (или Вся сеть).
Вы почти наверняка захотите использовать в своей системе Slackware уровень безопасности user.
Если шифрование паролей не включено, вы не сможете использовать Samba с системами NT4.0, Win2k, WinXP и Win2003. Для предыдущих версий операционных систем Windows для предоставления доступа к общим ресурсам шифрование не требовалось.
SMB является протоколом с аутентификацией, т.е. вы можете указать имя пользователя и пароль, чтобы воспользоваться возможностями этой службы. Мы сообщаем серверу samba о том, что имена пользователей и пароли верны, посредством команды smbpasswd. smbpasswd допускает использование общих ключей для добавления как обычных пользователей, так и машин-пользователей (для SMB необходимо, чтобы вы добавили NETBIOS-имена компьютеров как машин-пользователей, ограничивая тем самым круг компьютеров, с которых может осуществляться аутентификация).
Важно учесть, что данное имя пользователя или имя машины должно уже существовать в файле /etc/passwd. Вы можете добиться этого с помощью команды adduser. Обратите внимание, что при использовании команды adduser для добавления имени компьютера к нему необходимо добавить знак доллара (“$”). Однако этого не нужно делать при работе с smbpasswd. Утилита smbpasswd самостоятельно добавляет знак доллара. Нарушение этого правила посредством adduser приведёт к ошибке при добавлении имени машины в samba.
#adduser machine$ |
NFS (Network File System) изначально была написана компанией Sun для Solaris - их реализации системы Unix. И хотя её значительно легче поднять и настроить по сравнению с SMB, NFS гораздо менее безопасна. Главным слабым местом в безопасности является несложность подмены идентификаторов пользователя и группы одной машины на идентификаторы с другой машины. В протоколе NFS не реализована аутентификация. Было заявлено, что в будущих версиях протокола NFS безопасность будет повышена, однако на время написания этой книги это ещё не было сделано.
Настройка NFS осуществляется через файл /etc/exports. Когда вы загрузите стандартный файл /etc/exports в редактор, вы увидите пустой файл с комментарием вверху на две строки. Нам надо будет добавить строку в файл exports для каждого из каталогов, которые мы хотим экспортировать, с перечнем клиентских рабочих станций, которым будет разрешён доступ к этому каталогу. Например, если нам нужно экспортировать каталог /home/foo для рабочей станции Bar, нам надо будет добавить в наш файл /etc/exports такую строку:
Как видите, существует несколько различных опций, однако большинство из них должны быть понятными из этого примера.
NFS полагает, что заданный пользователь с одной из машин в сети имеет один и тот же идентификатор на всех остальных машинах. Когда NFS-клиент делает попытку чтения или записи на NFS-сервер, UID передаётся как часть запроса на чтение/запись. Этот UID считается таким же, как если бы запрос был выполнен с локальной машины. Как видите, если кто-то сможет произвольным образом указать заданный UID при обращении к ресурсам на удалённой машине, неприятности могут случиться и случаются. Средство, отчасти позволяющее избежать этого, заключается в монтировании всех каталогов с параметром root_squash . Это переопределяет UID любого пользователя, объявившего себя root"ом, на другой UID, предотвращая таким образом root"овый доступ к файлам и каталогам в экспортируемом каталоге. Похоже, что root_squash включается по умолчанию по соображениям безопасности, однако авторы всё равно рекомендуют явно указывать его в своём файле /etc/exports.
Вы также можете экспортировать каталог на сервере непосредственно из командной строки, воспользовавшись командой exportfs, как показано ниже:
# exportfs -o rw,no_root_squash Bar:/home/foo |
Эта команда экспортирует каталог /home/foo для компьютера “Bar” и предоставляет ему доступ на чтение/запись. Кроме того на сервере NFS не включен параметр root_squash , означающий, что любой пользователь на Bar с UID “0” (UID root"а) будет иметь на сервере те же привилегии, что и root. Синтаксис выглядит довольно странно (обычно, когда вы указываете каталог в виде computer:/directory/file, вы ссылаетесь на файл в каталоге на заданном компьютере).
Дополнительную информацию о файле exports вы найдёте в странице руководства.
NFS: удобная и перспективная сетевая файловая система
Сетевая файловая система – это сетевая абстракция поверх обычной файловой системы, позволяющая удаленному клиенту обращаться к ней через сеть так же, как и при доступе к локальным файловым системам. Хотя NFS не является первой сетевой системой, она сегодня развилась до уровня наиболее функциональной и востребованной сетевой файловой системы в UNIX®. 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 использует стандартную архитектурную модель "клиент-сервер" (как показано на рисунке 2). Сервер отвечает за реализацию файловой системы совместного доступа и хранилища, к которому подключаются клиенты. Клиент реализует пользовательский интерфейс к общей файловой системе, смонтированной внутри локального файлового пространства клиента.
В ОС 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, первым действием выполняется операция 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 – 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 – самая популярная сетевая файловая система в 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, вызов удаленной процедуры, реализует иной подход к сетевому программированию. Программа клиента просто вызывает функции в программе сервера. Так это решено с точки зрения программиста, однако в действительности имеет место следующая последовательность действий.
Сетевое программирование, использующее stubы и библиотечные RPC подпрограммы использует интерфейсы прикладного программирования API (сокеты или TLI), однако пользовательские приложения (программа клиента и процедуры сервера, вызываемые клиентом) никогда не обращаются к API. Приложению клиента достаточно вызывать процедуру сервера, при этом все детали реализации спрятаны пакетом RPC, client stubом и server stubом.
Пакеты 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 вызовы. Преобразователь портов предоставляет четыре процедуры сервера:
Когда стартует программа сервер 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 сервера. На этом рисунке необходимо обратить внимание на следующее.
Рисунок 29.3 Типичные настройки NFS клиента и NFS сервера.
Большинство 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.
При этом осуществляются следующие шаги.
Подобная реализация отдает весь процесс монтирования, кроме системного вызова 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.
Требуется, чтобы NFS записи были синхронными (с ожиданием). Сервер не может ответить OK до тех пор, пока данные не были успешно записаны (и любая другая информация о файле, которая должна быть обновлена) на диск.
В действительности, приведенные имена процедур начинаются с префикса NFSPROC_, который мы опустили.
UDP или TCP?
NFS был исходно написан, чтобы использовать UDP, и эту возможность предоставляют все производители. Однако, более новые реализации, также поддерживают TCP. Поддержка TCP используется для работы в глобальных сетях, которые становится все быстрее. Поэтому использование NFS в настоящее время уже не ограничено локальными сетями.
Границы между локальными и глобальными сетями стираются, и все это происходит очень быстро. Времена возврата меняются в очень широком диапазоне, и все чаще возникает переполнение. Эти характеристики глобальных сетей приводят к тому, что все чаще в них используются алгоритмы, которые мы рассматривали для TCP - медленный старт и избежание переполнения. Так как UDP не предоставляет ничего похожего на эти алгоритмы, то они или им подобные должны быть встроены в NFS клиент и сервер, иначе необходимо использовать TCP.
NFS поверх TCP
Реализация NFS Berkeley Net/2 поддерживает как UDP, так и TCP. [ Macklem 1991] описывает эту реализацию. Давайте рассмотрим, чем отличается использование NFS при работе поверх 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 сервер может осуществить запрос разборщика любое количество раз, что не приведет к отрицательным результатам (может быть, кроме того, что будут заняты сетевые ресурсы).
В течение 1994 года были выпущены спецификации для версии 3 протокола NFS [ Sun Microsystems 1993]. Реализации, как ожидается, станут доступными в течение 1994 года.
Здесь вкратце описаны основные различия между версиями 2 и 3. Мы будем называть их V2 и V3.
Краткие выводы
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 запросов или откликов?