Разблокировать поток из другого процесса, в C ++ - PullRequest
0 голосов
/ 05 августа 2009

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

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

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

Спасибо.

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

Ответы [ 5 ]

2 голосов
/ 17 августа 2009

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

Для ОС Unix вы можете использовать:

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

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

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

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

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

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

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

Что следует помнить о Boost.Interprocess

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

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

1 голос
/ 05 августа 2009

РЕДАКТИРОВАТЬ: Я ошибочно думал, что вам нужна синхронизация между потоками, пересмотрено для 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() для сна до завершения.

ПРИМЕЧАНИЕ : метод семафоров может разрешить сигнализацию нескольких завершений, вы должны справиться с этим, установив максимальное количество под 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 или собственные переменные условия в Vista, см. Страницу Условные переменные MSDN для получения дополнительной информации.

Ссылки:

0 голосов
/ 10 августа 2009

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

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

Для переносимости используйте портативную библиотеку сокетов, такую ​​как boost или ptypes или что-либо еще.

0 голосов
/ 05 августа 2009

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

Другой подход - сделать опрос в отдельной ветке.

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

0 голосов
/ 05 августа 2009

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

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

...