Н.В. Вдовикина, А.В. Казунин, И.В. Машечкин, А.Н. Техехин - Системное программное обеспечение - взаимодействие процессов (1114927), страница 20
Текст из файла (страница 20)
память *//* предоставляем второму процессувозможность войти */sops.sem_op = 3; /* увеличение семафора на3 */semop(semid, &sops, 1);/* ждем, пока семафор будет открыт для 1гопроцесса - для следующей итерации цикла*/sops.sem_op = 0; /* ожидание обнулениясемафора */semop(semid, &sops, 1);} while (str[0] != ‘Q’);/* в данный момент второй процесс уже дочитализ разделяемой памяти и отключился от нее –можно ее удалять*/shmdt(shmaddr) ; /* отключаемся от разделяемойпамяти */shmctl(shmid, IPC_RMID, NULL);/* уничтожаем разделяемую память */semctl(semid, 0, IPC_RMID, (int) 0);/* уничтожаем семафор */return 0;}2й процесс:/* необходимо корректно определить существованиересурса, если он есть - подключиться */#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <string.h>#define NMAX256123int main(int argc, char **argv){key_t key;int semid, shmid;struct sembuf sops;char *shmaddr;char str[NMAX];key = ftok(“/usr/ter/exmpl”,’S’);/* создаем тот же самый ключ */semid = semget(key, 1, 0666 | IPC_CREAT);shmid = shmget(key, NMAX, 0666 | IPC_CREAT);/* аналогично предыдущему процессуинициализации ресурсов */-shmaddr = shmat(shmid, NULL, 0);sops.sem_num = 0;sops.sem_flg = 0;/* запускаем цикл */do {printf(“Waiting… \n”); /* ожидание насемафоре */sops.sem_op = -2;/* будем ожидать, пока “значение семафора”+ ”значение sem_op” не станетположительным, т.е.
пока значение семафоране станет как минимум 3 (3-2=1 > 0) */semop(semid, &sops, 1);/* теперь значение семафора равно 1 */strcpy(str, shmaddr); /* копируем строкуиз разд.памяти *//*критическая секция - работа сразделяемой памятью - в этот моментпервый процесс к разделяемой памятидоступа не имеет*/if (str[0] == ‘Q’){/*завершение работы - освобождаемразделяемую память */124shmdt(shmaddr);}/*после работы – обнулим семафор*/sops.sem_op=-1;semop(semid, &sops, 1);printf(“Read from shared memory: %s\n”,str);} while (str[0] != ‘Q’);return 0;}Отметим, что данный пример демонстрирует два разныхприема использования семафоров для синхронизации: первыйпроцесс блокируется в ожидании обнуления семафора, т.е. для того,чтобы он мог войти в критическую секцию, значение семафорадолжно стать нулевым; второй процесс блокируется при попыткеуменьшить значение семафора до отрицательной величины, длятого, чтобы этот процесс мог войти в критическую секцию, значениесемафора должно быть не менее 3.
Обратите внимание, что в данномпримере, помимо взаимного исключения процессов, достигаетсястрогая последовательность действий двух процессов: они получаютдоступ к критической секции строго по очереди.1257Взаимодействие процессов в сети.7.1 Механизм сокетов.Средства межпроцессного взаимодействия ОС UNIX,представленные в системе IPC, решают проблему взаимодействиядвух процессов, выполняющихся в рамках одной операционнойсистемы. Однако, очевидно, их невозможно использовать, когдатребуется организовать взаимодействие процессов в рамках сети.Это связано как с принятой системой именования, котораяобеспечивает уникальность только в рамках данной системы, так ивообще с реализацией механизмов разделяемой памяти, очередисообщений и семафоров, – очевидно, что для удаленноговзаимодействия они не годятся.
Следовательно, возникаетнеобходимостьвкаком-тодополнительноммеханизме,позволяющем общаться двум процессам в рамках сети. Однако еслиразработчики программ будут иметь два абсолютно разных подходак реализации взаимодействия процессов, в зависимости от того, наодной машине они выполняются или на разных узлах сети, им,очевидно, придется во многих случаях создавать два принципиальноразных куска кода, отвечающих за это взаимодействие.
Понятно, чтоэто неудобно и хотелось бы в связи с этим иметь некоторыйунифицированный механизм, который в определенной степенипозволял бы абстрагироваться от расположения процессов и давалбы возможность использования одних и тех же подходов длялокального и нелокального взаимодействия.
Кроме того, как толькомы обращаемся к сетевому взаимодействию, встает проблемамногообразия сетевых протоколов и их использования. Понятно, чтобыло бы удобно иметь какой-нибудь общий интерфейс,позволяющий пользоваться услугами различных протоколов повыбору пользователя.Обозначенные проблемы был призван решить механизм,впервые появившийся в UNIX – BSD (4.2) и названный сокетами(sockets).Сокеты представляют собой в определенном смыслеобобщение механизма каналов, но с учетом возможныхособенностей, возникающих при работе в сети.
Кроме того, онипредоставляют больше возможностей по передаче сообщений,например, могут поддерживать передачу экстренных сообщений внеобщего потока данных. Общая схема работы с сокетами любого типатакова: каждый из взаимодействующих процессов должен на своейстороне создать и отконфигурировать сокет, после чего процессы126должны осуществить соединение с использованием этой парысокетов. По окончании взаимодействия сокеты уничтожаются.Механизм сокетов чрезвычайно удобен при разработкевзаимодействующих приложений, образующих систему «клиентсервер». Клиент посылает серверу запросы на предоставлениеуслуги, а сервер отвечает на эти запросы.Схема использования механизма сокетов для взаимодействия врамках модели «клиент-сервер» такова.
Процесс-сервер запрашиваету ОС сокет и, получив его, присваивает ему некоторое имя (адрес),которое предполагается заранее известным всем клиентам, которыезахотят общаться с данным сервером. После этого сервер переходитв режим ожидания и обработки запросов от клиентов. Клиент, сосвоей стороны, тоже создает сокет и запрашивает соединение своегосокета с сокетом сервера, имеющим известное ему имя (адрес).После того, как соединение будет установлено, клиент и сервермогут обмениваться данными через соединенную пару сокетов.Ниже мы подробно рассмотрим функции, выполняющие всенеобходимые действия с сокетами, и напишем пример небольшойсерверной и клиентской программы, использующих сокеты.7.1.1 Типы сокетов.
Коммуникационный домен.Сокеты подразделяются на несколько типов в зависимости оттипа коммуникационного соединения, который они используют. Дваосновных типа коммуникационных соединений и, соответственно,сокетов представляет собой соединение с использованиемвиртуального канала и датаграммное соединение.Соединение с использованием виртуального канала – этопоследовательный поток байтов, гарантирующий надежнуюдоставку сообщений с сохранением порядка их следования. Данныеначинают передаваться только после того, как виртуальный каналустановлен, и канал не разрывается, пока все данные не будутпереданы. Примером соединения с установлением виртуальногоканала является механизм каналов в UNIX, аналогом такогосоединения из реальной жизни также является телефонный разговор.Заметим, что границы сообщений при таком виде соединений несохраняются, т.е.
приложение, получающее данные, должно самоопределять, где заканчивается одно сообщение и начинаетсяследующее. Такой тип соединения может также поддерживатьпередачу экстренных сообщений вне основного потока данных, еслиэто возможно при использовании конкретного выбранногопротокола.127Датаграммное соединение используется для передачиотдельных пакетов, содержащих порции данных – датаграмм. Длядатаграмм не гарантируется доставка в том же порядке, в каком онибыли посланы. Вообще говоря, для них не гарантируется доставкавообще, надежность соединения в этом случае ниже, чем приустановлении виртуального канала.
Однако датаграммныесоединения, как правило, более быстрые. Примером датаграммногосоединения из реальной жизни может служить обычная почта:письма и посылки могут приходить адресату не в том порядке, вкаком они были посланы, а некоторые из них могут и совсемпропадать.Поскольку сокеты могут использоваться как для локального,так и для удаленного взаимодействия, встает вопрос о пространствеадресов сокетов.
При создании сокета указывается так называемыйкоммуникационный домен, к которому данный сокет будетпринадлежать. Коммуникационный домен определяет форматыадресов и правила их интерпретации. Мы будем рассматривать дваосновных домена: для локального взаимодействия – домен AF_UNIXи для взаимодействия в рамках сети – домен AF_INET (префикс AFобозначает сокращение от «address family» – семейство адресов).
Вдомене AF_UNIX формат адреса – это допустимое имя файла, вдомене AF_INET адрес образуют имя хоста + номер порта.Заметим, что фактически коммуникационный доменопределяет также используемые семейства протоколов. Так, длядомена AF_UNIX это будут внутренние протоколы ОС, для доменаAF_INET – протоколы семейства TCP/IP. Современные системыподдерживают и другие коммуникационные домены, например BSDUNIX поддерживает также третий домен – AF_NS, использующийпротоколы удаленного взаимодействия Xerox NS.Ниже приведен набор функций для работы с сокетами.7.1.2 Создание и конфигурирование сокета.Создание сокета.#include <sys/types.h>#include <sys/socket.h>int socket (int domain, int type, int protocol)Функция создания сокета так и называется – socket().
У нееимеется три аргумента. Первый аргумент – domain – обозначаеткоммуникационный домен, к которому должен принадлежатьсоздаваемый сокет. Для двух рассмотренных нами доменов128соответствующие константы будут равны, как мы уже говорили,AF_UNIX и AF_INET. Второй аргумент – type – определяет типсоединения, которым будет пользоваться сокет (и, соответственно,тип сокета). Для двух основных рассматриваемых нами типовсокетов это будут константы SOCK_STREAM для соединения сустановлением виртуального канала и SOCK_DGRAM для датаграмм12.Третий аргумент – protocol – задает конкретный протокол,которыйбудетиспользоватьсяврамкахданногокоммуникационного домена для создания соединения. Еслиустановить значение данного аргумента в 0, система автоматическивыберет подходящий протокол.
В наших примерах мы так и будемпоступать. Однако здесь для справки приведем константы дляпротоколов, используемых в домене AF_INET:IPPROTO_TCP – обозначает протокол TCP (корректно присоздании сокета типа SOCK_STREAM)IPPROTO_UDP – обозначает протокол UDP (корректно присоздании сокета типа SOCK_DGRAM)Функция socket() возвращаетв случае успехаположительное целое число – дескриптор сокета, которое можетбыть использовано в дальнейших вызовах при работе с даннымсокетом. Заметим, что дескриптор сокета фактически представляетсобой файловый дескриптор, а именно, он является индексом втаблице файловых дескрипторов процесса, и может использоваться вдальнейшем для операций чтения и записи в сокет, которыеосуществляются подобно операциям чтения и записи в файл(подробно эти операции будут рассмотрены ниже).В случае если создание сокета с указанными параметраминевозможно(например,принекорректномсочетаниикоммуникационного домена, типа сокета и протокола), функциявозвращает –1.Связывание.Для того чтобы к созданному сокету мог обратиться какойлибо процесс извне, необходимо присвоить ему адрес.