Билеты (Graur) (1114774), страница 24
Текст из файла (страница 24)
для того, чтобы он мог войти в критическую секцию,значение семафора должно стать нулевым; второй процесс блокируется припопытке уменьшить значение семафора до отрицательной величины, для того,чтобы этот процесс мог войти в критическую секцию, значение семафора должнобыть не менее 3. Обратите внимание, что в данном примере, помимо взаимногоисключения процессов, достигается строгая последовательность действий двухпроцессов: они получают доступ к критической секции строго по очереди.БИЛЕТ 36Механизм сокетов.Средства межпроцессного взаимодействия ОС UNIX, представленные всистеме IPC, решают проблему взаимодействия двух процессов, выполняющихся врамках одной операционной системы.
Однако, очевидно, их невозможноиспользовать, когда требуется организовать взаимодействие процессов в рамкахсети. Это связано как с принятой системой именования, которая обеспечиваетуникальность только в рамках данной системы, так и вообще с реализациеймеханизмов разделяемой памяти, очереди сообщений и семафоров, – очевидно, чтодля удаленного взаимодействия они не годятся. Следовательно, возникаетнеобходимость в каком-то дополнительном механизме, позволяющем общатьсядвум процессам в рамках сети.
Однако если разработчики программ будут иметьдва абсолютно разных подхода к реализации взаимодействия процессов, взависимости от того, на одной машине они выполняются или на разных узлах сети,им, очевидно, придется во многих случаях создавать два принципиально разныхкуска кода, отвечающих за это взаимодействие. Понятно, что это неудобно ихотелось бы в связи с этим иметь некоторый унифицированный механизм, которыйв определенной степени позволял бы абстрагироваться от расположения процессови давал бы возможность использования одних и тех же подходов для локального инелокального взаимодействия.
Кроме того, как только мы обращаемся к сетевомувзаимодействию, встает проблема многообразия сетевых протоколов и ихиспользования. Понятно, что было бы удобно иметь какой-нибудь общийинтерфейс, позволяющий пользоваться услугами различных протоколов по выборупользователя.Обозначенные проблемы был призван решить механизм, впервые появившийся вUNIX – BSD (4.2) и названный сокетами (sockets).Сокеты представляют собой в определенном смысле обобщение механизмаканалов, но с учетом возможных особенностей, возникающих при работе в сети.Кроме того, они предоставляют больше возможностей по передаче сообщений,например, могут поддерживать передачу экстренных сообщений вне общегопотока данных.
Общая схема работы с сокетами любого типа такова: каждый извзаимодействующих процессов должен на своей стороне создать иотконфигурировать сокет, после чего процессы должны осуществить соединение сиспользованием этой пары сокетов. По окончании взаимодействия сокетыуничтожаются.Механизм сокетов чрезвычайно удобен при разработке взаимодействующихприложений, образующих систему «клиент-сервер». Клиент посылает серверузапросы на предоставление услуги, а сервер отвечает на эти запросы.Схема использования механизма сокетов для взаимодействия в рамках модели«клиент-сервер» такова. Процесс-сервер запрашивает у ОС сокет и, получив его,присваивает ему некоторое имя (адрес), которое предполагается заранее известнымвсем клиентам, которые захотят общаться с данным сервером.
После этого серверпереходит в режим ожидания и обработки запросов от клиентов. Клиент, со своейстороны, тоже создает сокет и запрашивает соединение своего сокета с сокетомсервера, имеющим известное ему имя (адрес). После того, как соединение будетустановлено, клиент и сервер могут обмениваться данными через соединеннуюпару сокетов. Ниже мы подробно рассмотрим функции, выполняющие всенеобходимые действия с сокетами, и напишем пример небольшой серверной иклиентской программы, использующих сокеты.Типы сокетов.
Коммуникационный домен.Сокеты подразделяются на несколько типов в зависимости от типакоммуникационного соединения, который они используют. Два основных типакоммуникационных соединений и, соответственно, сокетов представляет собойсоединение с использованием виртуального канала и датаграммное соединение.Соединение с использованием виртуального канала – это последовательный потокбайтов, гарантирующий надежную доставку сообщений с сохранением порядка ихследования.
Данные начинают передаваться только после того, как виртуальныйканал установлен, и канал не разрывается, пока все данные не будут переданы.Примером соединения с установлением виртуального канала является механизмканалов в UNIX, аналогом такого соединения из реальной жизни также являетсятелефонный разговор. Заметим, что границы сообщений при таком видесоединений не сохраняются, т.е.
приложение, получающее данные, должно самоопределять, где заканчивается одно сообщение и начинается следующее. Такой типсоединения может также поддерживать передачу экстренных сообщений внеосновного потока данных, если это возможно при использовании конкретноговыбранного протокола.Датаграммное соединение используется для передачи отдельных пакетов,содержащих порции данных – датаграмм.
Для датаграмм не гарантируетсядоставка в том же порядке, в каком они были посланы. Вообще говоря, для них негарантируется доставка вообще, надежность соединения в этом случае ниже, чемпри установлении виртуального канала. Однако датаграммные соединения, какправило, более быстрые. Примером датаграммного соединения из реальной жизниможет служить обычная почта: письма и посылки могут приходить адресату не втом порядке, в каком они были посланы, а некоторые из них могут и совсемпропадать.Поскольку сокеты могут использоваться как для локального, так и для удаленноговзаимодействия, встает вопрос о пространстве адресов сокетов.
При созданиисокета указывается так называемый коммуникационный домен, к которому данныйсокет будет принадлежать. Коммуникационный домен определяет форматыадресов и правила их интерпретации. Мы будем рассматривать два основныхдомена: для локального взаимодействия – домен AF_UNIX и для взаимодействия врамках сети – домен AF_INET (префикс AF обозначает сокращение от «addressfamily» – семейство адресов). В домене AF_UNIX формат адреса – это допустимоеимя файла, в домене AF_INET адрес образуют имя хоста + номер порта.Заметим, что фактически коммуникационный домен определяет такжеиспользуемые семейства протоколов. Так, для домена AF_UNIX это будутвнутренние протоколы ОС, для домена AF_INET – протоколы семейства TCP/IP.Современные системы поддерживают и другие коммуникационные домены,например BSD UNIX поддерживает также третий домен – AF_NS, использующийпротоколы удаленного взаимодействия Xerox NS.Ниже приведен набор функций для работы с сокетами.Создание и конфигурирование сокета.Создание сокета.#include <sys/types.h>#include <sys/socket.h>int socket (int domain, int type, int protocol)Функция создания сокета так и называется – socket().
У нее имеется триаргумента. Первый аргумент – domain – обозначает коммуникационный домен, ккоторому должен принадлежать создаваемый сокет. Для двух рассмотренных намидоменов соответствующие константы будут равны, как мы уже говорили,AF_UNIX и AF_INET. Второй аргумент – type – определяет тип соединения,которым будет пользоваться сокет (и, соответственно, тип сокета).
Для двухосновных рассматриваемых нами типов сокетов это будут константыSOCK_STREAM для соединения с установлением виртуального канала иSOCK_DGRAM для датаграмм5. Третий аргумент – protocol – задает конкретныйпротокол, который будет использоваться в рамках данного коммуникационногодомена для создания соединения.
Если установить значение данного аргумента в 0,система автоматически выберет подходящий протокол. В наших примерах мы так ибудем поступать. Однако здесь для справки приведем константы для протоколов,используемых в домене AF_INET:IPPROTO_TCP – обозначает протокол TCP (корректно при создании сокета типаSOCK_STREAM)IPPROTO_UDP – обозначает протокол UDP (корректно при создании сокета типаSOCK_DGRAM)Функция socket() возвращает в случае успеха положительное целое число –дескриптор сокета, которое может быть использовано в дальнейших вызовах приработе с данным сокетом. Заметим, что дескриптор сокета фактическипредставляет собой файловый дескриптор, а именно, он является индексом втаблице файловых дескрипторов процесса, и может использоваться в дальнейшемдля операций чтения и записи в сокет, которые осуществляются подобнооперациям чтения и записи в файл (подробно эти операции будут рассмотреныниже).В случае если создание сокета с указанными параметрами невозможно (например,при некорректном сочетании коммуникационного домена, типа сокета ипротокола), функция возвращает –1.Связывание.Для того чтобы к созданному сокету мог обратиться какой-либо процесс извне,необходимо присвоить ему адрес.
Как мы уже говорили, формат адреса зависит откоммуникационного домена, в рамках которого действует сокет, и можетпредставлять собой либо путь к файлу, либо сочетание IP-адреса и номера порта.5Заметим, что данный аргумент может принимать не только указанные два значения,например, тип сокета SOCK_SEQPACKET обозначает соединение с установлением виртуального каналасо всеми вытекающими отсюда свойствами, но при этом сохраняются границы сообщений; однако данныйтип сокетов не поддерживается ни в домене AF_UNIX, ни в домене AF_INET, поэтому мы его здесьрассматривать не будемНо в любом случае связывание сокета с конкретным адресом осуществляетсяодной и той же функцией bind:#include <sys/types.h>#include <sys/socket.h>int bind (int sockfd, struct sockaddr *myaddr, intaddrlen)Первый аргумент функции – дескриптор сокета, возвращенный функциейsocket(); второй аргумент – указатель на структуру, содержащую адрес сокета.Для домена AF_UNIX формат структуры описан в <sys/un.h> и выглядитследующим образом:#include <sys/un.h>struct sockaddr_un {short sun_family; /* == AF_UNIX */char sun_path[108];};Для домена AF_INET формат структуры описан в <netinet/in.h> и выглядитследующим образом:#include <netinet/in.h>struct sockaddr_in {short sin_family; /* == AF_INET */u_short sin_port; /* port number */struct in_addr sin_addr; /* host IP address */char sin_zero[8]; /* not used */};Последний аргумент функции задает реальный размер структуры, на которуюуказывает myaddr.Важно отметить, что если мы имеем дело с доменом AF_UNIX и адрес сокетапредставляет собой имя файла, то при выполнении функции bind() система вкачестве побочного эффекта создает файл с таким именем.