Рубрики

Межпроцессное взаимодействие (IPC)

Процесс может быть двух типов:

  • Независимый процесс.
  • Кооперационный процесс.

Выполнение других процессов не влияет на независимый процесс, в то время как на процесс взаимодействия могут влиять другие выполняющиеся процессы. Хотя можно подумать, что те процессы, которые выполняются независимо, будут выполняться очень эффективно, но на практике существует много ситуаций, когда кооперативный характер можно использовать для увеличения скорости вычислений, удобства и модульности. Межпроцессное взаимодействие (IPC) — это механизм, который позволяет процессам связываться друг с другом и синхронизировать свои действия. Связь между этими процессами можно рассматривать как метод сотрудничества между ними. Процессы могут общаться друг с другом, используя эти два способа:

  1. Общая память
  2. Передача сообщений

На рисунке 1 ниже показана базовая структура связи между процессами с помощью метода общей памяти и передачи сообщений.

Операционная система может реализовать оба метода связи. Сначала мы обсудим метод связи с общей памятью, а затем передачу сообщений. Связь между процессами, использующими разделяемую память, требует, чтобы процессы разделяли некоторую переменную, и это полностью зависит от того, как программист ее реализует. Один из способов коммуникации с использованием разделяемой памяти можно представить так: предположим, что process1 и process2 выполняются одновременно, и они совместно используют некоторые ресурсы или используют некоторую информацию из другого процесса, process1 генерирует информацию об определенных используемых вычислениях или ресурсах и сохраняет ее как запись в Общая память. Когда процесс2 должен использовать общую информацию, он проверяет записи, хранящиеся в общей памяти, принимает к сведению информацию, созданную процессом1, и действует соответствующим образом. Процессы могут использовать разделяемую память для извлечения информации в виде записи из другого процесса, а также для доставки какой-либо конкретной информации другому процессу.
Давайте обсудим пример взаимодействия между процессами с использованием метода общей памяти.

я) метод общей памяти

Пример: проблема производителя и потребителя
Есть два процесса: производитель и потребитель. Производитель производит некоторый предмет, а Потребитель потребляет этот предмет. Эти два процесса совместно используют общее пространство или область памяти, известную как буфер, где хранится элемент, созданный Producer, и где Потребитель потребляет элемент при необходимости. Существует две версии этой проблемы: первая известна как проблема неограниченного буфера, в которой Producer может продолжать производить элементы, а размер буфера не ограничен, вторая известна как проблема ограниченного буфера, в которой производитель может создавать до определенное количество товара и после этого он начинает ждать, пока потребитель его потребит. Мы обсудим проблему ограниченного буфера. Сначала продюсер и потребитель будут делиться некоторой общей памятью, затем продюсер начнет производство предметов. Если общее количество произведенного предмета равно размеру буфера, производитель будет ждать, пока его не потребит потребитель. SIM-
т. е. потребитель сначала проверяет наличие товара, и, если товар недоступен, потребитель будет ждать, пока производитель его произведет. Если есть доступные предметы, потребитель будет их потреблять. Псевдокод приведен ниже:
Общие данные между двумя процессами

#define buff_max 25
#define mod %

  

    struct item{

  

        // другой элемент полученных данных

        // или потребленные данные

        ---------

    }

      

    // Массив необходим для хранения элементов.

    // Это общее место, которое будет

    // доступ по обоим процессам

    // item shared_buff [buff_max];

       

    // Две переменные, которые будут отслеживать

    // индексы товаров, произведенных производителем

    // и потребитель Свободный индекс указывает на

    // следующий свободный индекс. Полный индекс указывает на

    // первый полный индекс.

    int free_index = 0;

    int full_index = 0;

   

Код процесса производителя

item nextProduced;

      

    while(1){

          

        // проверяем, нет ли места

        // для производства.

        // если так, продолжай ждать.

        while((free_index+1) mod buff_max == full_index);

          

        shared_buff[free_index] = nextProduced;

        free_index = (free_index + 1) mod buff_max;

    }

Код потребительского процесса

item nextConsumed;

      

    while(1){

          

        // проверяем, есть ли в наличии

        // предмет для потребления.

        // если не продолжать ждать

        // получить их.

        while((free_index == full_index);

          

        nextConsumed = shared_buff[full_index];

        full_index = (full_index + 1) mod buff_max;

    }

В приведенном выше коде, производитель начнет производить снова, когда мод max (free_index + 1) buff будет свободен, потому что если он не свободен, это означает, что есть все еще предметы, которые могут быть потреблены потребителем, поэтому нет необходимости производить больше. Точно так же, если свободный индекс и полный индекс указывают на один и тот же индекс, это означает, что нет элемента для потребления.

II) способ передачи сообщений

Теперь мы начнем обсуждение взаимодействия между процессами посредством передачи сообщений. В этом методе процессы взаимодействуют друг с другом без использования какой-либо общей памяти. Если два процесса p1 и p2 хотят взаимодействовать друг с другом, они действуют следующим образом:

  • Установите канал связи (если ссылка уже существует, нет необходимости устанавливать ее снова.)
  • Начните обмениваться сообщениями, используя основные примитивы.
    Нам нужно как минимум два примитива:
    отправить (сообщение, адресат) или отправить (сообщение)
    получить (сообщение, хост) или получить (сообщение)

Размер сообщения может быть фиксированного размера или переменного размера. если он имеет фиксированный размер, он прост для разработчика ОС, но сложен для программиста, а если он имеет переменный размер, то он прост для программиста, но сложен для разработчика ОС. Стандартное сообщение может состоять из двух частей: заголовка и тела.
Часть заголовка используется для хранения типа сообщения, идентификатора назначения, идентификатора источника, длины сообщения и управляющей информации. Управляющая информация содержит информацию, например, что делать, если заканчивается буферное пространство, порядковый номер, приоритет. Как правило, сообщение отправляется в стиле FIFO.

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

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

  1. Как устанавливаются ссылки?
  2. Может ли ссылка быть связана с более чем двумя процессами?
  3. Сколько может быть связей между каждой парой взаимодействующих процессов?
  4. Какова емкость ссылки? Является ли размер сообщения, которое может содержать ссылка, фиксированным или переменным?
  5. Является ли ссылка однонаправленной или двунаправленной?

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

Направленное общение осуществляется через уничтоженный почтовый ящик (порт), который состоит из очереди сообщений. Отправитель хранит сообщение в почтовом ящике, а получатель забирает его.

Передача сообщений через обмен сообщениями.

Синхронная и асинхронная передача сообщений:
Заблокированный процесс — это процесс, ожидающий какого-либо события, например, когда ресурс станет доступным или завершится операция ввода-вывода. IPC возможен между процессами на одном компьютере, а также между процессами, запущенными на другом компьютере, т.е. в сетевой / распределенной системе. В обоих случаях процесс может блокироваться или не блокироваться при отправке сообщения или попытке получить сообщение, поэтому передача сообщений может быть блокирующей или неблокирующей. Блокировка считается синхронной, а блокировка отправки означает, что отправитель будет заблокирован, пока сообщение не будет получено получателем. Аналогично, блокировка приема имеет блок получателя, пока сообщение не станет доступным. Неблокирующая передача считается асинхронной, а при неблокирующей отправке отправитель отправляет сообщение и продолжает работу. Аналогично, при неблокирующем получении получатель получает действительное сообщение или ноль. После тщательного анализа мы можем прийти к выводу, что для отправителя более естественным является неблокирование после передачи сообщения, поскольку может возникнуть необходимость отправить сообщение различным процессам, но отправитель ожидает подтверждения от получателя в случае, если отправка не удалась. Точно так же более естественно для получателя блокировать после выдачи приема, поскольку информация из полученного сообщения может использоваться для дальнейшего выполнения, но в то же время, если отправка сообщения продолжает сбой, получателю придется ждать неопределенно долго , Вот почему мы также рассматриваем другую возможность передачи сообщений. Есть в основном три наиболее предпочтительные комбинации:

  • Блокировка отправки и блокировка получения
  • Неблокирующая отправка и Неблокирующая отправка
  • Неблокирующая отправка и блокировка получения (в основном используется)

При прямой передаче сообщений процесс, который хочет связаться, должен явно указать имя получателя или отправителя сообщения.
Например, отправить (p1, сообщение) означает отправить сообщение на p1.
аналогично, получение (p2, сообщение) означает получение сообщения от p2.
В этом способе связи линия связи устанавливается автоматически, которая может быть как однонаправленной, так и двунаправленной, но одна линия может использоваться между одной парой отправителя и получателя, а одна пара отправителя и получателя не должна иметь более одной пары ссылка на сайт. Симметрия и асимметрия между отправителем и получателем также могут быть реализованы, то есть либо оба процесса будут называть друг друга для отправки и получения сообщений, либо только отправитель будет называть получателя для отправки сообщения, и нет необходимости в том, чтобы получатель называл отправителя для получения сообщения. сообщение. Проблема с этим способом связи состоит в том, что, если имя одного процесса изменяется, этот метод не будет работать.

При непрямой передаче сообщений процессы используют почтовые ящики (также называемые портами) для отправки и получения сообщений. Каждый почтовый ящик имеет уникальный идентификатор, и процессы могут взаимодействовать, только если они совместно используют почтовый ящик. Ссылка устанавливается только в том случае, если процессы имеют общий почтовый ящик и одна ссылка может быть связана со многими процессами. Каждая пара процессов может совместно использовать несколько каналов связи, и эти каналы могут быть однонаправленными или двунаправленными. Предположим, что два процесса хотят общаться через непрямую передачу сообщений. Необходимые операции: создать почтовый ящик, использовать этот почтовый ящик для отправки и получения сообщений, уничтожить почтовый ящик. Используются следующие стандартные примитивы: send (A, message), что означает отправку сообщения в почтовый ящик A. Примитив для получения сообщения также работает таким же образом, например, получен (A, message) . В этой реализации почтового ящика есть проблема. Предположим, существует более двух процессов, совместно использующих один и тот же почтовый ящик, и предположим, что процесс p1 отправляет сообщение в почтовый ящик, какой процесс будет получателем? Эту проблему можно решить либо путем принудительного предоставления доступа к одному почтовому ящику только двум процессам, либо путем принудительного выполнения только одного процесса в определенный момент времени для получения или выбора любого процесса случайным образом и уведомления отправителя о получателе. Почтовый ящик может быть закрыт для одной пары отправитель / получатель, а также может использоваться несколькими парами отправитель / получатель. Порт является реализацией такого почтового ящика, который может иметь несколько отправителей и один получатель. Он используется в клиент-серверном приложении (здесь сервер является получателем). Порт принадлежит процессу приема и создается ОС по запросу процесса получателя и может быть уничтожен либо по запросу того же процесса получателя, либо когда получатель завершает свою работу. Обеспечение того, что только одному процессу разрешено выполнять получение, может быть выполнено с использованием концепции взаимного исключения. Почтовый ящик Mutex — это создание, которое совместно используется процессом. Отправитель неблокирует и отправляет сообщение. Первый процесс, который выполняет прием, войдет в критическую секцию, а все остальные процессы будут блокированы и будут ждать.

Теперь давайте обсудим проблему «производитель-потребитель», используя концепцию передачи сообщений. Производитель помещает элементы (внутри сообщений) в почтовый ящик, а потребитель может использовать элемент, когда в почтовом ящике присутствует хотя бы одно сообщение. Код приведен ниже:

Код производителя

void Producer(void){

          

        int item;

        Message m;

          

        while(1){

              

            receive(Consumer, &m);

            item = produce();

            build_message(&m , item ) ;

            send(Consumer, &m);

        }

    }

Код потребителя

void Consumer(void){

          

        int item;

        Message m;

          

        while(1){

              

            receive(Producer, &m);

            item = extracted_item();

            send(Producer, &m);

            consume_item(item);

        }

    }

Примеры систем IPC

  1. Posix: использует метод разделяемой памяти.
  2. Mach: использует передачу сообщений
  3. Windows XP: использует передачу сообщений с использованием локальных процедурных вызовов

Связь в клиент / серверной архитектуре:

Существуют различные механизмы:

  • труба
  • Разъем
  • Удаленные процедурные вызовы (RPC)

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

Ссылки:

  1. Концепции операционной системы от Galvin et al.
  2. Конспект лекций / статья Ариэля Дж. Франка, Университет Бар-Илан

Больше ссылки:
http://nptel.ac.in/courses/106108101/pdf/Lecture_Notes/Mod%207_LN.pdf
https://www.youtube.com/watch?v=lcRqHwIn5Dk

Эта статья предоставлена Durgesh Pandey . Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме. Если вам нравится GeeksforGeeks и вы хотите внести свой вклад, вы также можете написать статью и отправить ее по почте на contrib@geeksforgeeks.org. Смотрите свою статью, появляющуюся на главной странице GeeksforGeeks, и помогите другим вундеркиндам.

Рекомендуемые посты:

Межпроцессное взаимодействие (IPC)

0.00 (0%) 0 votes