Механизмы межпроцессного взаимодействия в операционной системе Unix

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 23:00, 30 марта 2015.

Каналы

FIFО – используется каналами при межпроцессовом взаимодействии.

  • Именованные каналы.
  • Неименованные каналы.

Идентичны по форме обращения.

Неименованные каналы

Поддерживают обмен данными только между процессами-родственниками, например, между предком и потомком или между потомками одного предка.

pipe(fdptr);

где fdptr - это указатель на массив из двух целых чисел, в который после создания неименованного программного канала будут помещены дескрипторы, предназначенные для чтения из программного канала (с помощью системного вызова read) и записи в программный канал (с помощью системного вызова write).

Есть некая иерархия процессов

Unix - interprocess communication (Named Pipes).png

Именованные каналы

Могут быть использованы для коммуникации любых, необязательно родственных, процессов. Каналы указанных типов создаются и открываются по-разному, но используются одинаково.

Один процесс направляет (записывает) данные в канал. Другой процесс получает (читает) данные из канала. В большинстве версий OS UNIX канал является однонаправленным механизмом, чтобы реализовать обмен данными в двух направлениях нужно предусмотреть 2 разнонаправленных канала:

Unix - interprocess communication (Channels).png

Сигналы

Для передачи сообщений об асинхроссых событиях. Либо ядром процессу, либо одним процессом другому посылается сигнал.

  1. Сигналы, обеспечивающие завершение процесса.
  2. Возникновение особых ситуаций в системе (нехватка ресурсов). Аппаратные ошибки, выход за адресное пространство.
  3. Неожиданные ситуации.
  4. Сигналы, которые посылаются процессу, находящегося в режиме выполнения.
  5. Сигналы терминального взаимодействия.
  6. Обеспечивают трассировку процесса.

В пространстве каждого процесса содержится битовая таблица. Для каждого сигнала определен адрес функции, которая является обработчиком.

Есть стандартный вызов сигнала kill(). Kill – 9,123 //завершить 123-й процесс, 9 - завершение.

Ядро, получив вызов, видит кто кому посылает сигнал. Устанавливает бит в 1 (в нашем случае в 9 бит). Ядро может вывести процесс из режима ожидания этого сигнала.

Процесс получает сигнал когда происходит переход из ядра в режим пользователя. Пока есть необработанные сигналы, сигнал не пойдет в режим пользователя.

Обработка сигнала:

  • Завершение процесса.
    • Штатное.
    • Аварийной.
  • Выполнение особой функции (может быть пользовательская).
  • Процесс может проигнорировать данный сигнал. Может быть определена маска, которая может игнорировать какие-либо сигналы.

Сообщения

Аналогия электронной почты, однако, работает между процессами.

Четыре системных вызова:

  • Msgget для образования новой очереди сообщений или получения дескриптора существующей очереди.
  • Msgsnd для посылки сообщения (его постановки в очередь сообщений).
  • Msgrcv для приема сообщения (выборки сообщения из очереди).
  • msgctl для выполнения управляющих действий.

msgqid = msgget(key, flag);

Сообщения хранятся в виде связного списка.

Дескриптор очереди сообщений - индекс в массиве заголовков очередей сообщений

В заголовке очереди хранятся:

  • указатели на первое и последнее сообщение в данной очереди.
  • число сообщений.
  • общий размер в байтах сообщений, находящихся в очереди.
  • идентификаторы процессов, которые последними послали или приняли сообщение через данную очередь.
  • временные метки последних выполненных операций msgsnd, msgrsv и msgctl.

msgsnd(msgqid, msg, count,flag);

  • msg - это указатель на структуру, содержащую целочисленный тип сообщения и символьный массив.
  • count – задает размер сообщения в байтах.
  • flag определяет действия ядра при выходе за пределы допустимых размеров внутренней буферной памяти.

Условия успешной постановки сообщения в очередь:

  • процесс должен иметь право на запись в очередь.
  • длина сообщения не должна превосходить верхний предел.
  • общая длина сообщений не должна превосходить установленного предела.
  • тип сообщения должен быть положительным целым числом.
  • процесс продолжает свое выполнение.
  • ядро активизирует (пробуждает) все процессы, ожидающие поступления сообщений из очереди.
  • превышается верхний предел суммарной длины сообщений.
  • обратившийся процесс откладывается до разгрузки очереди.
  • но есть флаг IPC_NOWAIT (как для семафоров).

count = msgrcv(id, msg,maxcount, type, flag);

  • msg - указатель на структуру данных в адресном пространстве пользователя для размещения принятого сообщения
  • maxcount - размер области данных (массива байтов) в структуре msg.
  • type специфицирует тип сообщения, которое желательно принять.
  • flag указывает ядру, что следует предпринять, если в указанной очереди сообщений отсутствует сообщение с указанным типом.
  • count - реальное число байтов, переданных пользователю.

Значением параметра type:

  • Значением параметра type является нуль.
    • выбирается первое сообщение.
    • копируется в заданную пользовательскую структуру данных.
    • процессы, отложенные по причине переполнения очереди сообщений, активизируются
    • если значение параметра maxcount оказывается меньше реального размера сообщения, ядро не удаляет сообщение из очереди и возвращает код ошибки.
    • если задан флаг MSG_NOERROR, то выборка сообщения производится, и в буфер пользователя переписываются первые maxcount байтов сообщения.
  • Значение type есть положительное целое число.
    • выбирается первое сообщение с таким же типом.
  • Значение type есть отрицательное целое число.
    • выбирается первое сообщение, значение типа которого меньше или равно абсолютному значению type.
  • В очереди отсутствуют сообщения, соответствующие спецификации type.
    • процесс откладывается до появления в очереди требуемого сообщения.
    • но есть флаг IPC_NOWAIT.

msgctl(id, cmd, mstatbuf);

  • опрос состояния описателя очереди сообщений.
  • изменение его состояния.
  • уничтожение очереди сообщений.

Разделение памяти

Процессы в виртуальной памяти выделяют общую область для взаимодействия.

4 базовых вызова:

  • shmget создает новый сегмент разделяемой памяти или находит существующий сегмент с тем же ключом.
  • shmat подключает сегмент с указанным дескриптором к виртуальной памяти обращающегося процесса.
  • shmdt отключает от виртуальной памяти ранее подключенный к ней сегмент с указанным виртуальным адресом начала.
  • shmctl служит для управления параметрами, связанными с существующим сегментом.

После подключения сегмента разделяемой памяти к виртуальной памяти процесса, он может обращаться к соответствующим элементам памяти с использованием обычных машинных команд чтения и записи.

shmid = shmget(key, size, flag);

  • size определяет желаемый размер сегмента в байтах.
  • если в таблице разделяемой памяти находится элемент, содержащий заданный ключ, и права доступа не противоречат текущим характеристикам процесса, то значением системного вызова является дескриптор существующего сегмента.
  • реальный размер сегмента можно узнать с помощью системного вызова shmctl.
  • иначе создается новый сегмент с размером не меньше установленного в системе минимального размера сегмента разделяемой памяти и не больше установленного максимального размера.
  • создание сегмента не означает немедленного выделения под него основной памяти.
  • откладывается до выполнения первого системного вызова подключения сегмента к виртуальной памяти некоторого процесса при выполнении последнего системного вызова отключения сегмента от виртуальной памяти соответствующая основная память освобождается.

virtaddr = shmat(id, addr,flags);

  • id - это ранее полученный дескриптор сегмента.
  • addr – желаемый процессом виртуальный адрес, который должен соответствовать началу сегмента в виртуальной памяти.
  • virtaddr – реальный виртуальный адрес начала сегмента.
  • не обязательно совпадает со значением прямого параметра addr.
  • если addr ==0, ядро выбирает наиболее удобный виртуальный адрес начала сегмента.

shmdt(addr);

  • addr - виртуальный адрес начала сегмента в виртуальной памяти, ранее полученный от системного вызова shmat

shmctl(id, cmd, shsstatbuf);

  • cmd идентифицирует требуемое конкретное действие

Семафоры

Для синхронизации процессов, для организации доступа к различным ресурсам.

Три системных вызова:

  • semget для создания и получения доступа к набору семафоров.
  • semop для манипулирования значениями семафоров.
  • semctl для выполнения управляющих операций над набором семафоров.

id = semget(key, count, flag);

  • key, flag и id - обычный смысл.
  • count – число семафоров в наборе семафоров, обладающих одним и тем же ключом.
  • индивидуальный семафор идентифицируется дескриптором набора семафоров и номером семафора в наборе.
  • если набор семафоров с указанным ключом уже существует, то число семафоров в группе можно узнать с помощью системного вызова semctl.

oldval = semop(id, oplist,count);

  • id - дескриптор группы семафоров.
  • oplist – массив описателей операций над семафорами группы.
  • count – размер этого массива возвращается значение последнего обработанного семафора.

Элемент массива oplist:

  • номер семафора в указанном наборе семафоров.
  • операция.
  • флаги.
  • Если проверка прав доступа проходит нормально
    • указанные в массиве oplist номера семафоров не выходят за пределы общего размера набора семафоров
  • для каждого элемента массива oplist значение семафора изменяется в соответствии со значением поля "операция"
  • Значение поля операции положительно
    • значение семафора увеличивается на единицу
    • все процессы, ожидающие увеличения значения семафора, активизируются (пробуждаются)
  • Значение поля операции равно нулю
    • если значение семафора равно нулю, выбирается следующий элемент массива oplist
    • иначе число процессов, ожидающих нулевого значения семафора, увеличивается на единицу
    • обратившийся процесс переводится в состояние ожидания (усыпляется)
  • Значение поля операции отрицательно
    • его абсолютное значение меньше или равно значению семафора
      • это отрицательное значение прибавляется к значению семафора
      • если значение семафора стало нулевым, то ядро активизирует все процессы, ожидающие нулевого значения этого семафора
    • значение семафора меньше абсолютной величины поля операции
      • число процессов, ожидающих увеличения значения семафора увеличивается на единицу
      • текущий процесс откладывается

semctl(id, number, cmd, arg);

  • id - это дескриптор группы семафоров.
  • number - номер семафора в группе.
  • cmd - код операции.
  • arg – указатель на структуру, содержимое которой интерпретируется в зависимости от операции.

Выводы

Механизм для синхронизации - семафор, явно ориентированный на это. Группа из каналов, сообщений и разделения памяти ориентирована на передачу блоков информации. Если механизм сообщений предполагает очередность (аналог - почта) и упорядоченность, то разделение памяти - между двумя приложениями быстрый способ передачи большого объема. Механизм каналов - для формального обмена, удобная организация этого механизма. Механизм сигналов является механизмом межпроцессного взаимодействия: когда нужно донести информацию о том, что факт наступил.