eCo Software
не получает вознаграждение
из США

 
Обновление

 
Программы

 
(Санкт-Петербург)

 
Преимущества (1)

 
Разработчику (1)

 
(Пайпы программ)

 
Компании: (1)

 
История (1):

 
(Бонусы)

 
Советы:

 
(Барьеры и решения)

 
Технологии: (1)

 
(Применение в науке, лаборатории, ..)

 

 
Готовые решения:

 
Новая eComStation:

 
Будущее: (1)

 
(Ссылки на другие сайты)

 
(Картинка дня)

 
Артефакты OS/2

 
Гаджеты

РЕКЛАМА: ArcaOS 5.1 Русская версия
Пакет русификации ArcaOS 5.1 OS/2 давно доступен. Поддерживается любая версия: 5.1, 5.1.1.

eCo Software может выпустить и другие пакеты (Немецкий, Голландский, Бразильский Португальский, Испанский, Шведский и т.д.)

Взаимодействие между процессами


TITLE: Взаимодействие между процессами

DATE: 2012-08-11 17:56:09

AUTHOR: Capricorn

Введение

Любой программист, который пишет софт для многозадачной OS (а в наши дни других фактически не существует) рано или поздно сталкивается с необходимостью обеспечить взаимодействие между несколькими программами, которые должны работать в связке. В OS/2 для этой цели существует несколько механизмов: семафоры, пайпы, общая (разделяемая) память, очереди. Если с первыми двумя всё более-менее понятно и программисты активно используют их, то очереди и общая память почему-то обделены вниманием. На мой взгляд, совершенно незаслуженно. Цель данной статьи - подробно рассмотреть данные механизмы и дать рекомендации по их использованию. Но сначала, рассмотрим первые два.

Семафоры

Семафоры служат одной цели: синхронизации процессов. У семафора всегда есть 2 состояния: "занят" и "свободен". Суть синхронизации состоит в том, что соответствующая команда ожидания проверяет, занят ли семафор, и если да, замораживает Всего существует 2 вида семафоров: ивэнты и мутексы.

а) Семафор типа "event" ("событие") нужен для того, чтобы позволить одному треду дождаться, пока другой тред выполнит некоторую задачу.

Пример:

/*************/
/*           */
/* Процесс 1 */
/*           */
/*************/

#define INCL_DOS
#include 

PSZ  szSemName  = "\\SEM32\\EVENT"; /* Имя семафора. Должно иметь префикс \SEM32\ */
HEV  hevEvent1  = 0;                /* Дескриптор семафора */

if (DosCreateEventSem(szSemName,    /* Имя создаваемого семафора  */
                    &hevEvent1,     /* Сюда будет возвращён дескриптор семафора */
                    DC_SEM_SHARED,  /* Разделяемый семафор */
                    FALSE))         /* Создаём семафор в сброшенном (занятом) состоянии */
   return 1;  /* Семафор создать не удалось */

/* Тут что-то делаем 
   До этого момента другой тред будет ждать
   срабатывания (освобождения) семафора */

DosPostEventSem(hevEvent); /* Командуем семафору сработать (освободиться) */
  
/* Продолжаем работу */

DosCloseEventSem(hevEvent1);      /* Избавляемся от семафора */

 

/*************/
/*           */
/* Процесс 2 */
/*           */
/*************/


Трубы (pipes)

[дополнение]

Разделяемая память

[дополнение]

Очереди

Ещё один способ взаимодействия между процессами - очереди (queues). Как уже говорилось ранее, очереди почему-то обойдены вниманием в пользу труб (pipes). На мой взгляд, совершенно незаслуженно. Очень часто очереди оказываются намного удобнее. Но, всё по-порядку.

Итак, очередь представляет собой механизм обмена сообщениями. Они чем-то напоминают очереди сообщений Presentation Manager'а, но есть существенные различия, поэтому не стоит их путать. Главное различие состоит в том, что не смотря на название, очереди могут работать не только в режиме собственно, очередей (FIFO), но и в режиме стека (LIFO), а также, по приоритетам.

Очереди всегда именованные.

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

Пример:

/**********************/
/*                    */
/* Процесс 1 (сервер) */
/*                    */
/**********************/

#define INCL_DOS
#include 

#define QUEUE_FIFO 0	// Очередь
#define QUEUE_LIFO 1	// Стек
#define QUEUE_PRIO 2	// По приоритетам

#define MSG_QUIT   0x0001 /* Идентификатор сообщения для завершения цикла */

#define QUEUE_NAME "\\QUEUES\\special.que"	/* Имя очереди.
						 * Должно иметь префикс \QUEUES\
						 */

/* Функция, которая будет обрабатывать сообщения */
BOOL processMessage(ULONG ulMessageId, ULONG ulDataSize, PVOID pvData);

int main(void)
{
	HQUEUE hQueue;	/* Сюда будет помещён хэндл очереди */
	APIRET rc;	/* Результат вызова функций API */	

	/* Открываем очередь */
	rc = DosCreateQueue(&hQueue, QUEUE_FIFO, QUE_NAME);
	if (rc)
		return rc;
		
	/* Цикл обработки сообщений из очереди */	
	while(TRUE)
	{
		REQUESTDATA requestData;        /* Структура для помещения данных запроса */
		ULONG       ulDataSize;         /* Сюда будет помещён объём присланных данных */
		PVOID       pvData;             /* Сюда будет помещена ссылка на присланные данные */
		rc = DosReadQueue(hQueue,       /* Хэндл очереди */
                                 &requestData, /* Данные запроса */
                                 &ulDataSize,  /* Объём присланных данных */
                                 &pvData,      /* Присланные данные */
                                 0,            /* Читаем первый элемент из очереди */
                                 FALSE,        /* Ждём */
                                 0,            /* Приоритет  не нужен */
                                 NULLHANDLE);  /* Нэндл семафора-собатия  не нужен */
		if (rc || requestData.ulData==MSG_QUIT)
			break;
		processMessage(ulMessageId, ulDataSize, pvData);
	}
	rc = DosCloseQueue(hQueue);             /* Удаляем очередь */
	return rc;
}

 

/**********************/
/*                    */
/* Процесс 2 (клиент) */
/*                    */
/**********************/

#define MSG_QUIT   0x0001 /* Идентификатор сообщения для завершения цикла */

#define QUEUE_NAME "\\QUEUES\\special.que"	/* Имя очереди.
						 * Должно иметь префикс \QUEUES\
#define INCL_DOS
#include 

int main(void)
{
	HQUEUE hQueue;	/* Сюда будет помещён хэндл очереди */
	APIRET rc;	/* Результат вызова функций API */	
	PID	pid;	/* Идентификатор процесса, создавшего очередь */

	/* Открываем очередь */
	rc = DosOpenQueue(&pid, &hQueue, QUE_NAME);
	if (rc)
		return rc;

	rc = DosWriteQueue(hQueue, MSG_QUIT, 0L, NULL, 0L); /* Записываем в очередь сообщение*/
	rc = DosCloseQueue(hQueue);                         /* Закрываем очередь */
	return rc;
}

В данном примере мы первый процесс создаёт и слушает очередь. Другой процесс открывает очередь и записывает туда определённое нами сообщение о завершении работы (MSG_QUIT). Первый процесс, получив это сообщение, завершает свою работу.

Обратите внимание, что функция DosCloseQueue() по сути, удаляет хэндл очереди. Как только все хэндлы очереди будут удалены, удалится и сама очередь.

Так в чём же преимущество очередей перед трубами? Дело в том, что при использовании труб мы фактически имеем дело с непрерывным потоком данных. Это удобно, когда необходимо постоянно передавать большие объёмы данных. Но такие случаи очень редки. Чаще бывает нужно, чтобы один процесс сообщал другому о неких событиях или передавал какие-то команды, на которые другой процесс должен реагировать. В данном случае очереди гораздо удобнее, т. к. сообщение, помещённое в очередь как раз и является такой командой.

 

Попробуй программу:

T&V HappyPlayer - управление телеприемниками Brooktree 848/878

Комментарии:

Прокомментируйте эту статью (напоминаем, автор работал над текстом несколько недель, уважайте мнение других).


Ваше имя:

Ваш E-Mail:

CODE:
312241......

  

Ваш комментарий:


Писать программы для eComStation - это выгодно: a) система имеет более компактный API, который хорошо продуман и эффективен, b) Рынок не такой бесконечный, как у Windows. Все пользователи eComStation узнают про ваш продукт, c) Один разработчик значительно влияет на всю ОС.

Статьи

Операционная система
Программное обеспечение
Оборудование
Для разработчика
Разное
Колонка редактора


Готовая eComStation на SSD диске

 





Последний активный опрос: Какая высота барьера RPM?

[Google]

IBM OS/2 Warp

 
Обучение новичков

Отчет: OS/2 совместимое оборудование

 
Статьи


   
  Почему eComStation?
Возможности
Особенности
Применение
Ролики и скриншоты
   eComStation для
для бизнесменов
для студентов и инженеров
для продавцов компьютеров
сообщество пользователей
   Разработчик
Распространить программу
Описание API, библиотеки
Начать новый проект
Конкурсы
   Программы
Он-лайн каталог
Выбрать через eCo Market
   Служба поддержки
Отправить вопрос
Купить eComStation
Вопросы и ответы
Обучение новичков
 
 
© 2001 - 2025 eCo Software, All rights reserved
Сибирский Медведь **********
eComStation Serenity Systems International • OS/2 Warp IBM Corporation • ArcaOS Arca Noae