Вопрос

Я программирую модуль межпроцессной связи (Процесс A и Процесс B).

Есть ли какой-либо способ, которым поток связи в B может запускаться (быть разблокирован), как только процесс A завершает определенное действие, я имею в виду, без B выполнения какого-либо опроса или B слишком долгого ожидания после A завершения своего действия?

Какие концепции / модели / шаблоны проектирования регулируют эти проблемы?(Что-то более точное, чем синхронизация между процессами).Какие библиотеки / методы вы рекомендуете?

Спасибо.

Редактировать:Я ищу методы, подходящие для каждой из трех основных операционных систем:Ms Windows, Apple Mac OS X, GNU/ Linux.

Это было полезно?

Решение

Это довольно тяжелая работа:

Для операционных систем Unix вы можете использовать:

  • условие pthread и мьютекс с аргументом setpshared.

    Примечание:он хорошо поддерживается в Linux 2.6, Solaris, но не поддерживается FreeBSD и Cygwin (не знаю о Mac OS X)

  • Для Unix-файлов вы также можете использовать именованные семафоры, но я не знаю их уровень поддержки

  • Для Windows есть несколько событий...

Это тяжелая работа, особенно для IPC...

Так что, если вам нужно что-то переносимое, я бы посоветовал взглянуть на Boost.Межпроцессный процесс, в котором есть условия и мьютексы...

Но убедитесь, что все функции поддерживаются во всех операционных системах, которые вы хотите поддерживать.

Что следует отметить о Boost.Межпроцессный

Тщательно проверьте уровень поддержки для каждой ОС Unix, с которой вам нужно работать, потому что Boost.Interprosess использует функции pthread_*, которые не всегда поддерживаются...а затем возвращается к эмуляции - проверьте качество такой эмуляции

Также проверьте, как это работает в Windows - насколько я знаю, в Win32 API нет мьютексов "в общей памяти", обычно следует использовать именованные объекты, поэтому проверьте, что поддерживается и как.

Другие советы

Редактировать: Я ошибочно подумал, что вам нужна синхронизация между потоками, исправленная для IPC

Я думаю, вам нужно что-то вроде ожидаемых событий.

В Windows вы можете использовать CreateEvent(), чтобы создать (или получить существующее) именованное событие автоматического сброса.

Когда процесс A завершает обработку, он должен вызвать SetEvent(), в то время как процесс B должен вызывать WaitForSingleObject() перейти в режим ожидания до завершения (или тайм-аута).

В качестве альтернативы вы можете использовать семафоры, созданные CreateSemaphore(), инициализирован значением 0.Процесс A сигнализирует о завершении, вызывая ReleaseSemaphore(), в то время как процесс B снова использует WaitForSingleObject() дождаться завершения.

В Linux и OS X вы можете использовать семафоры с аналогичным эффектом.использование sem_open() чтобы создать именованный семафор с 0 в качестве начального значения.

Когда процесс A завершается, он должен вызвать sem_post() чтобы увеличить семафор, в то время как процесс B должен вызывать sem_wait() спать до завершения.

ПРИМЕЧАНИЕ:метод semaphore может позволять сигнализировать о нескольких завершениях, вы должны справиться с этим, установив максимальное количество в Windows или проверив текущее значение sem на работоспособность с помощью sem_getvalue()


Я думаю, что переменные условия соответствуют тому, что вы пытаетесь сделать, вот пример, который будет работать в Linux и OSX

#include <pthread.h>
/* no error checking, quick and dirty sample */
pthread_mutex_t g_mutex;
pthread_cond_t g_cond;
int a_done = 0;

void init(void)
{
    pthread_mutex_init(&g_mutex, NULL);
    pthread_cond_init(&g_cond, NULL);
}

void thread_a(void *arg)
{
    /* do something here... */
    pthread_mutex_lock(&g_mutex);
    a_done = 1;
    pthread_cond_signal(&g_cond);
    pthread_mutex_unlock(&g_mutex);
}

void thread_b(void *arg)
{
    /* wait for a to complete */
    pthread_mutex_lock(&g_mutex);
    while (!a_done)
        pthread_cond_wait(&g_cond, &g_mutex);
    a_done = 0;
    pthread_mutex_unlock(&g_mutex);
}

В Windows вы можете использовать pthreads-win32-pthreads-потоки-win32, или собственные переменные условия в Vista, см. Переменные условия MSDN страница для получения дополнительной информации.

Ссылки:

Если ваша ОС поддерживает сигналы, вы могли бы разблокировать мьютекс из обработчика сигналов и отправить сигнал из процесса A, как только вы завершите задачу.

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

Наиболее распространенным является использование select() /poll().Оба могут проверять несколько файловых дескрипторов, если есть доступные входные данные.Оба получают параметр тайм-аута - это предотвратит ожидание занятости, которое может потреблять 100% процессора.Это очень подходящее решение для небольших / средних применений.

Другой подход заключается в проведении опроса в отдельном потоке.

Если вы собираетесь разрабатывать большое приложение, стоит обратить внимание на Фреймворк ACE или повышение.Эти фреймворки представляют собой кроссплатформенные решения, хорошо разработанные и хорошо протестированные.

Что ж, по моему мнению и опыту, лучший способ сделать это портативным и простым способом - использовать сокеты.Кроме того, вы получаете возможность использовать два процесса на разных компьютерах (при необходимости).Кроме того, вы можете расширить коммуникацию, чтобы обрабатывать больше, чем синхронно.

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

Чтобы быть переносимым, используйте переносимую библиотеку сокетов, такую как повышение или типы pt или что там еще.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top