Domanda

Sto programmando un modulo di comunicazione tra processi (processo A e processo B).

Esiste un modo in cui il thread di comunicazione in B può essere eseguito (essere sbloccato) non appena il processo A termina un'azione specifica, intendo senza che B esegua alcun polling o B che attenda troppo dopo che A termina la sua azione?

Quali sono i concetti / modelli / modelli di progettazione che governano questi problemi? (Qualcosa di più preciso della sincronizzazione tra processi). Quali librerie / metodi mi consigliate?

Grazie.

Modifica: sto cercando metodi adatti per ciascuno dei tre sistemi operativi principali: Windows, Apple Mac OS X, GNU / Linux.

È stato utile?

Soluzione

Questo è un lavoro piuttosto difficile:

Per i sistemi operativi Unix è possibile utilizzare:

  • condizione pthread e mutex con argomento setpshared.

    Nota: è supportato bene sotto Linux 2.6, Solaris, ma non supporta FreeBSD e Cygwin (non conosco Mac OS X)

  • Per Unix puoi anche usare semafori nominati, ma non conosco il loro livello di supporto

  • Per Windows ci sono alcuni eventi ...

Questo è un duro lavoro, specialmente per IPC ...

Quindi, se vuoi qualcosa di portatile, ti suggerisco di dare un'occhiata a Boost. Interprocesso che ha condizioni e mutex ...

Ma assicurati che tutte le funzionalità siano supportate su tutti i sistemi operativi che desideri supportare.

Elementi da tenere presenti su Boost.Interprocess

Controlla attentamente il livello di supporto per ogni sistema operativo Unix con cui devi lavorare, perché Boost.Interprosess utilizza funzioni pthread_ * che non sono sempre supportate ... e quindi non riesce a tornare all'emulazione - controlla la qualità di tale emulazione

Inoltre, controlla come funziona questa roba su Windows - per quanto ne so che non esiste alcuna "memoria condivisa" mutex nell'API Win32, in genere si dovrebbero usare oggetti con nome, quindi controllare cosa è supportato e come.

Altri suggerimenti

EDIT: ho erroneamente pensato che avessi bisogno della sincronizzazione tra thread, revisionata per IPC

Penso che tu abbia bisogno di qualcosa di simile ad eventi attendibili.

In Windows puoi usare CreateEvent ( ) , per creare (o ottenere un evento esistente) denominato, ripristino automatico.

Quando il processo A completa l'elaborazione, dovrebbe chiamare < code> SetEvent () , mentre il processo B dovrebbe chiamare WaitForSingleObject () per dormire fino al completamento (o timeout).

In alternativa, puoi utilizzare i semafori creati da CreateSemaphore () , inizializzato su 0. Il processo A segnala il completamento chiamando ReleaseSemaphore () , mentre il processo B utilizza nuovamente WaitForSingleObject () per attendere il completamento.

In Linux e OS X puoi usare i semafori con un effetto simile. usa sem_open () per creare un semaforo denominato, con 0 come valore iniziale.

Al termine del processo A, dovrebbe chiamare sem_post () per incrementare il semaforo, mentre il processo B dovrebbe chiamare sem_wait () per dormire fino al completamento.

NOTA : il metodo del semaforo può consentire la segnalazione di più completamenti, è necessario gestirlo impostando un conteggio massimo in Windows o controllando il valore sem corrente per sanità mentale con sem_getvalue ()


Penso che le variabili di condizione si adattino a ciò che stai cercando di fare, ecco un esempio che funzionerebbe su Linux e 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);
}

In Windows, puoi utilizzare pthreads-win32 o variabili di condizioni native in Vista, vedi la pagina Variabili di condizione MSDN per ulteriori informazioni.

References:

Se il sistema operativo in uso supporta i segnali, è possibile sbloccare un mutex da un gestore di segnali e inviare il segnale dal processo A non appena si termina l'attività.

Il processo B sarebbe in attesa di un mutex o di un altro strumento di sincronizzazione e A lavorerebbe su qualunque cosa, quindi quando finisce, per esempio, invia il segnale USR1 e il gestore USR1 nel processo B sblocca lo strumento di sincronizzazione corrispondente.

Il più comune è usare select () / poll (). Entrambi possono controllare diversi descrittori di file se c'è input disponibile. Entrambi ricevono un parametro di timeout - questo eviterà l'attesa di occupato, che potrebbe consumare il 100% di CPU. Questa è una soluzione molto adatta per applicazioni medio / piccole.

Un altro approccio è quello di effettuare il polling in thread separati.

Se hai intenzione di sviluppare una grande applicazione, vale la pena guardare ACE framework o boost . Questi framework sono soluzioni multipiattaforma, ben progettate e testate.

Beh, secondo la mia opinione ed esperienza, il modo migliore per farlo in modo portatile e semplice è usare le prese. Inoltre hai la possibilità di avere i due processi su macchine diverse (se necessario). Inoltre puoi estendere la comunicazione per gestire qualcosa di più della sincronizzazione.

Se non si desidera eseguire il polling, utilizzare un thread in attesa di un messaggio di sincronizzazione su un socket. Hai letto il socket in modo bloccante. Quando si riceve il messaggio, si utilizza una sincronizzazione multithread standard per gestire la sincronizzazione. Nel tuo caso, poiché B dovrebbe aspettare fino alla fine di A, devi solo leggere in modo bloccante nel tuo processo.

Per essere portatile, utilizzare una libreria di prese portatili come boost o ptypes o altro.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top