The design of the unix operating system by Maurice J
Вид материала | Реферат |
11.3 Взаимодействие в сети |
- Лекция 10. Файловые системы Unix, 116.79kb.
- Уровни рассмотрения, 314.07kb.
- Курс по операционным системам (на примере ос windows) Основан на учебном курсе Windows, 29.21kb.
- Выполнил ученик 11 «А» класса, 443.51kb.
- Ос лекция 1 (2-й семестр – временно), 101.4kb.
- Operating System, 7686.97kb.
- Unix-подобные операционные системы, характеристики, особенности, разновидности, 40.63kb.
- 1. ms sql server. Общие сведения, 66.03kb.
- Shanti ananda maurice, 89.84kb.
- Методические материалы, 3002.45kb.
семафором все обусловленные действия.
Ядро создает структуру восстановления всякий раз, когда про-
цесс уменьшает значение семафора, а удаляет ее, когда процесс
увеличивает значение семафора, поскольку установочное значение
----------------TT-------┐ ----------------TT-------T-------┐
│ идентификатор ││ │ │ идентификатор ││ │ │
│ семафора ││ semid │ │ семафора ││ semid │ semid │
+---------------++-------+ +---------------++-------+-------+
│ номер семафора││ 0 │ │ номер семафора││ 0 │ 1 │
+---------------++-------+ +---------------++-------+-------+
│ установочное ││ │ │ установочное ││ │ │
│ значение ││ 1 │ │ значение ││ 1 │ 1 │
L---------------++-------- L---------------++-------+--------
(а) После первой операции (б) После второй операции
----------------TT-------┐
│ идентификатор ││ │
│ семафора ││ semid │
+---------------++-------+
│ номер семафора││ 0 │ пусто
+---------------++-------+
│ установочное ││ │
│ значение ││ 1 │
L---------------++--------
(в) После третьей операции (г) После четвертой операции
Рисунок 11.17. Последовательность состояний списка структур
восстановления
структуры равно 0. На Рисунке 11.17 показана последовательность
состояний списка структур при выполнении программы с параметром
'a'. После первой операции процесс имеет одну структуру, состоя-
щую из идентификатора semid, номера семафора, равного 0, и уста-
новочного значения, равного 1, а после второй операции появляется
вторая структура с номером семафора, равным 1, и установочным
значением, равным 1. Если процесс неожиданно завершается, ядро
проходит по всем структурам и прибавляет к каждому семафору по
единице, восстанавливая их значения в 0. В частном случае ядро
уменьшает установочное значение для семафора 1 на третьей опера-
ции, в соответствии с увеличением значения самого семафора, и
удаляет всю структуру целиком, поскольку установочное значение
становится нулевым. После четвертой операции у процесса больше
нет структур восстановления, поскольку все установочные значения
стали нулевыми.
Векторные операции над семафорами позволяют избежать взаимных
блокировок, как было показано выше, однако они представляют из-
вестную трудность для понимания и реализации, и в большинстве
приложений полный набор их возможностей не является обязательным.
Программы, испытывающие потребность в использовании набора сема-
форов, сталкиваются с возникновением взаимных блокировок на поль-
зовательском уровне, и ядру уже нет необходимости поддерживать
такие сложные формы системных функций.
Синтаксис вызова системной функции semctl:
semctl(id,number,cmd,arg);
Параметр arg объявлен как объединение типов данных:
union semunion {
int val;
struct semid_ds *semstat; /* описание типов см. в При-
* ложении */
unsigned short *array;
} arg;
Ядро интерпретирует параметр arg в зависимости от значения
параметра cmd, подобно тому, как интерпретирует команды ioctl
(глава 10). Типы действий, которые могут использоваться в пара-
метре cmd: получить или установить значения управляющих парамет-
ров (права доступа и др.), установить значения одного или всех
семафоров в наборе, прочитать значения семафоров. Подробности по
каждому действию содержатся в Приложении. Если указана команда
удаления, IPC_RMID, ядро ведет поиск всех процессов, содержащих
структуры восстановления для данного семафора, и удаляет соот-
ветствующие структуры из системы. Затем ядро инициализирует ис-
пользуемые семафором структуры данных и выводит из состояния при-
останова все процессы, ожидающие наступления некоторого связанно-
го с семафором события: когда процессы возобновляют свое выполне-
ние, они обнаруживают, что идентификатор семафора больше не явля-
ется корректным, и возвращают вызывающей программе ошибку.
11.2.4 Общие замечания
Механизм функционирования файловой системы и механизмы взаи-
модействия процессов имеют ряд общих черт. Системные функции типа
"get" похожи на функции creat и open, функции типа "control" пре-
доставляют возможность удалять дескрипторы из системы, чем похожи
на функцию unlink. Тем не менее, в механизмах взаимодействия про-
цессов отсутствуют операции, аналогичные операциям, выполняемым
системной функцией close. Следовательно, ядро не располагает све-
дениями о том, какие процессы могут использовать механизм IPC, и,
действительно, процессы могут прибегать к услугам этого механиз-
ма, если правильно угадывают соответствующий идентификатор и если
у них имеются необходимые права доступа, даже если они не выпол-
нили предварительно функцию типа "get". Ядро не может автомати-
чески очищать неиспользуемые структуры механизма взаимодействия
процессов, поскольку ядру неизвестно, какие из этих структур
больше не нужны. Таким образом, завершившиеся вследствие возник-
новения ошибки процессы могут оставить после себя ненужные и не-
используемые структуры, перегружающие и засоряющие систему. Нес-
мотря на то, что в структурах механизма взаимодействия после
завершения существования процесса ядро может сохранить информацию
о состоянии и данные, лучше все-таки для этих целей использовать
файлы.
Вместо традиционных, получивших широкое распространение фай-
лов механизмы взаимодействия процессов используют новое прост-
ранство имен, состоящее из ключей (keys). Расширить семантику
ключей на всю сеть довольно трудно, поскольку на разных машинах
ключи могут описывать различные объекты. Короче говоря, ключи в
основном предназначены для использования в одномашинных системах.
Имена файлов в большей степени подходят для распределенных систем
(см. главу 13). Использование ключей вместо имен файлов также
свидетельствует о том, что средства взаимодействия процессов яв-
ляются "вещью в себе", полезной в специальных приложениях, но не
имеющей тех возможностей, которыми обладают, например, каналы и
файлы. Большая часть функциональных возможностей, предоставляемых
данными средствами, может быть реализована с помощью других сис-
темных средств, поэтому включать их в состав ядра вряд ли следо-
вало бы. Тем не менее, их использование в составе пакетов прик-
ладных программ тесного взаимодействия дает лучшие результаты по
сравнению со стандартными файловыми средствами (см. Упражнения).
11.3 ВЗАИМОДЕЙСТВИЕ В СЕТИ
Программы, поддерживающие межмашинную связь, такие, как
электронная почта, программы дистанционной пересылки файлов и
удаленной регистрации, издавна используются в качестве специаль-
ных средств организации подключений и информационного обмена.
Так, например, стандартные программы, работающие в составе элект-
ронной почты, сохраняют текст почтовых сообщений пользователя в
отдельном файле (для пользователя "mjb" этот файл имеет имя "/usr
/mail/mjb"). Когда один пользователь посылает другому почтовое
сообщение на ту же машину, программа mail (почта) добавляет сооб-
щение в конец файла адресата, используя в целях сохранения це-
лостности различные блокирующие и временные файлы. Когда адресат
получает почту, программа mail открывает принадлежащий ему почто-
вый файл и читает сообщения. Для того, чтобы послать сообщение на
другую машину, программа mail должна в конечном итоге отыскать на
ней соответствующий почтовый файл. Поскольку программа не может
работать с удаленными файлами непосредственно, процесс, протекаю-
щий на другой машине, должен действовать в качестве агента ло-
кального почтового процесса; следовательно, локальному процессу
необходим способ связи со своим удаленным агентом через межмашин-
ные границы. Локальный процесс является клиентом удаленного обс-
луживающего (серверного) процесса.
Поскольку в системе UNIX новые процессы создаются с помощью
системной функции fork, к тому моменту, когда клиент попытается
выполнить подключение, обслуживающий процесс уже должен существо-
вать. Если бы в момент создания нового процесса удаленное ядро
получало запрос на подключение (по каналам межмашинной связи),
возникла бы несогласованность с архитектурой системы. Чтобы избе-
жать этого, некий процесс, обычно init, порождает обслуживающий
процесс, который ведет чтение из канала связи, пока не получает
запрос на обслуживание, после чего в соответствии с некоторым
протоколом выполняет установку соединения. Выбор сетевых средств
и протоколов обычно выполняют программы клиента и сервера, осно-
вываясь на информации, хранящейся в прикладных базах данных; с
другой стороны, выбранные пользователем средства могут быть зако-
дированы в самих программах.
В качестве примера рассмотрим программу uucp, которая обслу-
живает пересылку файлов в сети и исполнение команд на удалении
(см. [Nowitz 80]). Процесс-клиент запрашивает в базе данных адрес
и другую маршрутную информацию (например, номер телефона), откры-
вает автокоммутатор, записывает или проверяет информацию в деск-
рипторе открываемого файла и вызывает удаленную машину. Удаленная
машина может иметь специальные линии, выделенные для использова-
ния программой uucp; выполняющийся на этой машине процесс init
порождает getty-процессы - серверы, которые управляют линиями и
получают извещения о подключениях. После выполнения аппаратного
подключения процесс-клиент регистрируется в системе в соответс-
твии с обычным протоколом регистрации: getty-процесс запускает
специальный интерпретатор команд, uucico, указанный в файле "/etc
/passwd", а процесс-клиент передает на удаленную машину последо-
вательность команд, тем самым заставляя ее исполнять процессы от
имени локальной машины.
Сетевое взаимодействие в системе UNIX представляет серьезную
проблему, поскольку сообщения должны включать в себя как информа-
ционную, так и управляющую части. В управляющей части сообщения
может располагаться адрес назначения сообщения. В свою очередь,
структура адресных данных зависит от типа сети и используемого
протокола. Следовательно, процессам нужно знать тип сети, а это
идет вразрез с тем принципом, по которому пользователи не должны
обращать внимания на тип файла, ибо все устройства для пользова-
телей выглядят как файлы. Традиционные методы реализации сетевого
взаимодействия при установке управляющих параметров в сильной
степени полагаются на помощь системной функции ioctl, однако в
разных типах сетей этот момент воплощается по-разному. Отсюда
возникает нежелательный побочный эффект, связанный с тем, что
программы, разработанные для одной сети, в других сетях могут не
заработать.
Чтобы разработать сетевые интерфейсы для системы UNIX, были
предприняты значительные усилия. Реализация потоков в последних
редакциях версии V располагает элегантным механизмом поддержки
сетевого взаимодействия, обеспечивающим гибкое сочетание отдель-
ных модулей протоколов и их согласованное использование на уровне
задач. Следующий раздел посвящен краткому описанию метода решения
данных проблем в системе BSD, основанного на использовании гнезд.
11.4 ГНЕЗДА
В предыдущем разделе было показано, каким образом взаимодейс-
твуют между собой процессы, протекающие на разных машинах, при
этом обращалось внимание на то, что способы реализации взаимо-
действия могут быть различаться в зависимости от используемых
протоколов и сетевых средств. Более того, эти способы не всегда
применимы для обслуживания взаимодействия процессов, выполняющих-
ся на одной и той же машине, поскольку в них предполагается су-
ществование обслуживающего (серверного) процесса, который при вы-
полнении системных функций open или read будет приостанавливаться
драйвером. В целях создания более универсальных методов взаимо-
действия процессов на основе использования многоуровневых сетевых
протоколов для системы BSD был разработан механизм, получивший
название "sockets" (гнезда) (см. [Berkeley 83]). В данном разделе
мы рассмотрим некоторые аспекты применения гнезд (на пользова-
тельском уровне представления).
Процесс-клиент Процесс-сервер
│ │
│ │
L--┐ ----
--------------------------+--┐ ---+--------------------------┐
│ Уровень гнезд │ │ Уровень гнезд │
+-------------------------+--+ +--+--------------------------+
│ TCP │ │ TCP │
│ Уровень протоколов │ │ │ │ Уровень протоколов │
│ IP │ │ IP │
+-------------------------+--+ +--+--------------------------+
│ Драйвер│ │ Драйвер │
│ Уровень устройств Ethernet│ │Ethernet Уровень устройств │
L-------------------------+--- L--+---------------------------
L---┐ -----
│ │
│ │
С е т ь
Рисунок 11.18. Модель с использованием гнезд
Структура ядра имеет три уровня: гнезд, протоколов и уст-
ройств (Рисунок 11.18). Уровень гнезд выполняет функции интерфей-
са между обращениями к операционной системе (системным функциям)
и средствами низких уровней, уровень протоколов содержит модули,
обеспечивающие взаимодействие процессов (на рисунке упомянуты
протоколы TCP и IP), а уровень устройств содержит драйверы, уп-
равляющие сетевыми устройствами. Допустимые сочетания протоколов
и драйверов указываются при построении системы (в секции конфигу-
рации); этот способ уступает по гибкости вышеупомянутому потоко-
вому механизму. Процессы взаимодействуют между собой по схеме
клиент-сервер: сервер ждет сигнала от гнезда, находясь на одном
конце дуплексной линии связи, а процессы-клиенты взаимодействуют
с сервером через гнездо, находящееся на другом конце, который мо-
жет располагаться на другой машине. Ядро обеспечивает внутреннюю
связь и передает данные от клиента к серверу.
Гнезда, обладающие одинаковыми свойствами, например, опираю-
щиеся на общие соглашения по идентификации и форматы адресов (в
протоколах), группируются в домены (управляемые одним узлом). В
системе BSD 4.2 поддерживаются домены: "UNIX system" - для взаи-
модействия процессов внутри одной машины и "Internet" (межсете-
вой) - для взаимодействия через сеть с помощью протокола DARPA
(Управление перспективных исследований и разработок Министерства
обороны США) (см. [Postel 80] и [Postel 81]). Гнезда бывают двух
типов: виртуальный канал (потоковое гнездо, если пользоваться
терминологией Беркли) и дейтаграмма. Виртуальный канал обеспечи-
вает надежную доставку данных с сохранением исходной последова-
тельности. Дейтаграммы не гарантируют надежную доставку с сохра-
нением уникальности и последовательности, но они более экономны в
смысле использования ресурсов, поскольку для них не требуются
сложные установочные операции; таким образом, дейтаграммы полезны
в отдельных случаях взаимодействия. Для каждой допустимой комби-
нации типа домен-гнездо в системе поддерживается умолчание на ис-
пользуемый протокол. Так, например, для домена "Internet" услуги
виртуального канала выполняет протокол транспортной связи (TCP),
а функции дейтаграммы - пользовательский дейтаграммный протокол
(UDP).
Существует несколько системных функций работы с гнездами.
Функция socket устанавливает оконечную точку линии связи.
sd = socket(format,type,protocol);
Format обозначает домен ("UNIX system" или "Internet"), type -
тип связи через гнездо (виртуальный канал или дейтаграмма), а
protocol - тип протокола, управляющего взаимодействием. Дескрип-
тор гнезда sd, возвращаемый функцией socket, используется другими
системными функциями. Закрытие гнезд выполняет функция close.
Функция bind связывает дескриптор гнезда с именем:
bind(sd,address,length);
где sd - дескриптор гнезда, address - адрес структуры, определяю-
щей идентификатор, характерный для данной комбинации домена и
протокола (в функции socket). Length - длина структуры address;
без этого параметра ядро не знало бы, какова длина структуры,
поскольку для разных доменов и протоколов она может быть различ-
ной. Например, для домена "UNIX system" структура содержит имя
файла. Процессы-серверы связывают гнезда с именами и объявляют о
состоявшемся присвоении имен процессам-клиентам.
С помощью системной функции connect делается запрос на подк-
лючение к существующему гнезду:
connect(sd,address,length);
Семантический смысл параметров функции остается прежним (см.
функцию bind), но address указывает уже на выходное гнездо, обра-
зующее противоположный конец линии связи. Оба гнезда должны ис-
пользовать одни и те же домен и протокол связи, и тогда ядро
удостоверит правильность установки линии связи. Если тип гнезда -
дейтаграмма, сообщаемый функцией connect ядру адрес будет исполь-
зоваться в последующих обращениях к функции send через данное
гнездо; в момент вызова никаких соединений не производится.
Пока процесс-сервер готовится к приему связи по виртуальному
каналу, ядру следует выстроить поступающие запросы в очередь на
обслуживание. Максимальная длина очереди задается с помощью сис-
темной функции listen:
listen(sd,qlength)
где sd - дескриптор гнезда, а qlength - максимально-допустимое
число запросов, ожидающих обработки.
---------------------┐ --------------------------┐
│ Процесс-клиент │ │ Процесс-сервер │
│ │ │ │ │ │
│ │ │ │ ------ │
│ │ │ │ │ │
│ │ │ │listen addr accept addr│
L---------+----------- L-----+-------------------
│ │
L---------------------------
Рисунок 11.19. Прием вызова сервером
Системная функция accept принимает запросы на подключение,
поступающие на вход процесса-сервера:
nsd = accept(sd,address,addrlen);
где sd - дескриптор гнезда, address - указатель на пользователь-
ский массив, в котором ядро возвращает адрес подключаемого клиен-
та, addrlen - размер пользовательского массива. По завершении вы-
полнения функции ядро записывает в переменную addrlen размер
пространства, фактически занятого массивом. Функция возвращает
новый дескриптор гнезда (nsd), отличный от дескриптора sd. Про-
цесс-сервер может продолжать слежение за состоянием объявленного
гнезда, поддерживая связь с клиентом по отдельному каналу (Рису-
нок 11.19).
Функции send и recv выполняют передачу данных через подклю-
ченное гнездо. Синтаксис вызова функции send:
count = send(sd,msg,length,flags);
где sd - дескриптор гнезда, msg - указатель на посылаемые данные,
length - размер данных, count - количество фактически переданных
байт. Параметр flags может содержать значение SOF_OOB (послать
данные out-of-band - "через таможню"), если посылаемые данные не
учитываются в общем информационном обмене между взаимодействующи-
ми процессами. Программа удаленной регистрации, например, может
послать out-of-band сообщение, имитирующее нажатие на клавиатуре
терминала клавиши "delete". Синтаксис вызова системной функции
recv:
count = recv(sd,buf,length,flags);
где buf - массив для приема данных, length - ожидаемый объем дан-
ных, count - количество байт, фактически переданных пользователь-
ской программе. Флаги (flags) могут быть установлены таким обра-
зом, что поступившее сообщение после чтения и анализа его содер-
жимого не будет удалено из очереди, или настроены на получение