- •Н.В.Вдовикина, а.В.Казунин, и.В.Машечкин, а.Н.Терехин Системное программное обеспечение: взаимодействие процессов.
- •Часть I. Теоретические основы. 5
- •Часть II. Реализация процессов. 34
- •Часть III. Реализация взаимодействия процессов. 62
- •6.4Семафоры. 116
- •Часть I. Теоретические основы.
- •Введение.
- •Понятие процесса.
- •Некоторые типы процессов.
- •«Полновесные процессы»
- •«Легковесные процессы»
- •Жизненный цикл процесса.
- •Синхронизация параллельных процессов.
- •Способы реализации взаимного исключения.
- •Запрещение прерываний и специальные инструкции.
- •Алгоритм Петерсона.
- •Активное ожидание.
- •Семафоры.
- •Мониторы.
- •Дополнительная синхронизация: переменные-условия.
- •Обмен сообщениями.
- •Синхронизация.
- •Адресация.
- •Длина сообщения.
- •Классические задачи синхронизации процессов.
- •«Обедающие философы»
- •Задача «читателей и писателей»
- •Задача о «спящем парикмахере»
- •Часть II. Реализация процессов.
- •Реализация процессов в ос unix
- •Понятие процесса в unix.
- •Контекст процесса.
- •Тело процесса.
- •Аппаратный контекст.
- •Системный контекст.
- •Аппарат системных вызов в oc unix.
- •Порождение новых процессов.
- •Порождение сыновнего процесса. Идентификаторы процессов.
- •Порождение сыновнего процесса. Одновременное выполнение.
- •Механизм замены тела процесса.
- •Запуск на выполнение команды ls.
- •Вызов программы компиляции.
- •Использование схемы fork-exec
- •Завершение процесса.
- •Использование системного вызова wait()
- •Использование системного вызова wait()
- •Жизненный цикл процесса в ос unix.
- •Начальная загрузка. Формирование о и 1 процессов.
- •Планирование процессов в ос unix.
- •Планирование процессов.
- •Принципы организация свопинга.
- •Часть III. Реализация взаимодействия процессов.
- •Элементарные средства межпроцессного взаимодействия.
- •Сигналы.
- •Обработка сигнала.
- •Удаление временных файлов при завершении программы.
- •Программа “Будильник”.
- •Двухпроцессный вариант программы “Будильник”.
- •Надежные сигналы.
- •Работа с сигнальной маской.
- •Использование надежных сигналов.
- •Программные каналы
- •Использование канала.
- •Реализация конвейера.
- •Совместное использование сигналов и каналов – «пинг-понг».
- •Именованные каналы (fifo)
- •Модель «клиент-сервер».
- •Нелокальные переходы.
- •Использование нелокальных переходов.
- •Трассировка процессов.
- •Общая схема использования механизма трассировки.
- •Трассировка процессов.
- •Средства межпроцессного взаимодействия System V.
- •Организация доступа и именования в разделяемых ресурсах.
- •Именование разделяемых объектов.
- •Генерация ключей: функция ftok().
- •Общие принципы работы с разделяемыми ресурсами.
- •Очередь сообщений.
- •Доступ к очереди сообщений.
- •Отправка сообщения.
- •Получение сообщения.
- •Управление очередью сообщений.
- •Использование очереди сообщений.
- •Основной процесс.
- •Очередь сообщений. Модель «клиент-сервер»
- •Разделяемая память
- •Создание общей памяти.
- •Доступ к разделяемой памяти.
- •Открепление разделяемой памяти.
- •Управление разделяемой памятью.
- •Общая схема работы с общей памятью в рамках одного процесса.
- •Семафоры.
- •Доступ к семафору
- •Операции над семафором
- •Управление массивом семафоров.
- •Работа с разделяемой памятью с синхронизацией семафорами.
- •1Й процесс:
- •2Й процесс:
- •Взаимодействие процессов в сети.
- •Механизм сокетов.
- •Типы сокетов. Коммуникационный домен.
- •Создание и конфигурирование сокета. Создание сокета.
- •Связывание.
- •Предварительное установление соединения. Сокеты с установлением соединения. Запрос на соединение.
- •Сервер: прослушивание сокета и подтверждение соединения.
- •Прием и передача данных.
- •Завершение работы с сокетом.
- •Резюме: общая схема работы с сокетами.
- •Работа с локальными сокетами.
- •Пример работы с сокетами в рамках сети.
- •Среда параллельного программирования mpi
- •Краткий обзор параллельных архитектур.
- •Системы с распределенной памятью – mpp.
- •Системы с общей памятью – smp.
- •Системы с неоднородным доступом к памяти – numa.
- •Кластерные системы.
- •Модель программирования mpi.
- •Функции общего назначения. Общая структура программы.
- •Коммуникаторы и группы.
- •Обрамляющие функции. Инициализация и завершение.
- •Синхронизация: барьеры.
- •Использование барьерной синхронизации.
- •Прием и передача данных. Общие замечания.
- •Сообщения и их атрибуты.
- •Поддержка типов данных в mpi.
- •Коммуникации «точка-точка». Блокирующий режим.
- •Отправка сообщений в блокирующем режиме.
- •Режимы буферизации.
- •Прием сообщений в блокирующем режиме.
- •Mpi: прием сообщения, размер которого неизвестен заранее.
- •Коммуникации «точка-точка». Неблокирующий режим.
- •Отсылка и прием сообщений в неблокирующем режиме.
- •Работа с квитанциями.
- •Mpi: коммуникации «точка-точка». «Пинг-понг».
- •Коллективные коммуникации.
- •Коллективный обмен данными.
- •Коллективный обмен, совмещенный с обработкой данных.
- •Mpi: применение коллективных коммуникаций.
- •Алфавитный указатель упоминаемых библиотечных функций и системных вызовов.
- •Список литературы
Сервер: прослушивание сокета и подтверждение соединения.
Следующие два вызова используются сервером только в том случае, если используются сокеты с предварительным установлением соединения.
#include <sys/types.h>
#include <sys/socket.h>
int listen (int sockfd, int backlog);
Этот вызов используется процессом-сервером для того, чтобы сообщить системе о том, что он готов к обработке запросов на соединение, поступающих на данный сокет. До тех пор, пока процесс – владелец сокета не вызовет listen(), все запросы на соединение с данным сокетом будут возвращать ошибку. Первый аргумент функции – дескриптор сокета. Второй аргумент, backlog, содержит максимальный размер очереди запросов на соединение. ОС буферизует приходящие запросы на соединение, выстраивая их в очередь до тех пор, пока процесс не сможет их обработать. В случае если очередь запросов на соединение переполняется, поведение ОС зависит от того, какой протокол используется для соединения. Если конкретный протокол соединения не поддерживает возможность перепосылки (retransmission) данных, то соответствующий вызов connect() вернет ошибку ECONNREFUSED. Если же перепосылка поддерживается (как, например, при использовании TCP), ОС просто выбрасывает пакет, содержащий запрос на соединение, как если бы она его не получала вовсе. При этом пакет будет присылаться повторно до тех пор, пока очередь запросов не уменьшится и попытка соединения не увенчается успехом, либо пока не произойдет тайм-аут, определенный для протокола. В последнем случае вызов connect() завершится с ошибкой ETIMEDOUT. Это позволит клиенту отличить, был ли процесс-сервер слишком занят, либо он не функционировал. В большинстве систем максимальный допустимый размер очереди равен 5.
Конкретное соединение устанавливается при помощи вызова accept():
#include <sys/types.h>
#include <sys/socket.h>
int accept (int sockfd, struct sockaddr *addr, int *addrlen);
Этот вызов применяется сервером для удовлетворения поступившего клиентского запроса на соединение с сокетом, который сервер к тому моменту уже прослушивает (т.е. предварительно была вызвана функция listen()). Вызов accept() извлекает первый запрос из очереди запросов, ожидающих соединения, и устанавливает с ним соединение. Если к моменту вызова accept() очередь запросов на соединение пуста, процесс, вызвавший accept(), блокируется до поступления запросов.
Когда запрос поступает и соединение устанавливается, accept() создает новый сокет, который будет использоваться для работы с данным соединением, и возвращает дескриптор этого нового сокета, соединенного с сокетом клиентского процесса. При этом первоначальный сокет продолжает оставаться в состоянии прослушивания. Через новый сокет осуществляется обмен данными, в то время как старый сокет продолжает обрабатывать другие поступающие запросы на соединение (напомним, что именно первоначально созданный сокет связан с адресом, известным клиентам, поэтому все клиенты могут слать запросы только на соединение с этим сокетом). Это позволяет процессу-серверу поддерживать несколько соединений одновременно. Обычно это реализуется путем порождения для каждого установленного соединения отдельного процесса-потомка, который занимается собственно обменом данными только с этим конкретным клиентом, в то время как процесс-родитель продолжает прослушивать первоначальный сокет и порождать новые соединения (см. Пример 0.0.xxviii).
Во втором параметре передается указатель на структуру, в которой возвращается адрес клиентского сокета, с которым установлено соединение, а в третьем параметре возвращается реальная длина этой структуры. Благодаря этому сервер всегда знает, куда ему в случае надобности следует послать ответное сообщение. Если адрес клиента нас не интересует, в качестве второго аргумента можно передать NULL.