2009-08-05 8 views
0

Je programme un module de communication interprocessus (Process A et Process B).Débloquer un thread d'un autre processus, en C++

Y a-t-il un moyen pour que le thread de communication de B s'exécute (être déverrouillé) dès que le processus A termine une action spécifique, je veux dire sans B effectuant un sondage ou B attendant trop après que A termine son action?

Quels sont les concepts/modèles/modèles de conception qui régissent ces problèmes? (Quelque chose de plus précis que la synchronisation interprocess). Quelles bibliothèques/méthodes recommandez-vous?

Merci. Editer: Je suis à la recherche de méthodes adaptées à chacun des trois systèmes d'exploitation principaux: Ms Windows, Apple Mac OS X, GNU/Linux.

+0

J'ai mal compris la question en pensant qu'il s'agissait d'un problème inter-thread. J'ai ajouté des informations sur la façon de faire cela maintenant entre les processus, espérons que cela aide – Hasturkun

Répondre

2

C'est le travail assez difficile:

Pour Unix OSes vous pouvez utiliser:

  • état pthread et mutex avec l'argument setpshared.

    Note: il est bien supporté sous Linux 2.6, Solaris, mais il n'a pas pris en charge FreeBSD et Cygwin (ne savent pas sur Mac OS X)

  • Pour unix vous pouvez également utiliser les sémaphores nommés, mais je ne connaissent pas le niveau de soutien de leur

  • pour Windows, il y a des événements ...

C'est dur travail, en particulier pour les IPC ...

donc, si vous voulez quelque chose portabl e, je suggère de jeter un oeil sur Boost.Interprocess qui a des conditions et des mutex ...

Mais assurez-vous que toutes les fonctionnalités prises en charge sur tous les systèmes d'exploitation que vous voulez soutenir.

Ce que vous devez noter à propos Boost.Interprocess

Vérifiez soigneusement le niveau de soutien pour chaque système d'exploitation Unix, vous devez travailler avec, car Boost.Interprosess utilise des fonctions pthread_ * qui ne sont pas toujours prises en charge ... puis revient à l'émulation - vérifiez la qualité d'une telle émulation

De même, vérifiez comment cela fonctionne sur Windows - pour autant que je sache qu'il existe pas de mutex "en mémoire partagée" dans l'API Win32, les objets généralement nommés doivent être utilisés, vérifiez donc ce qui est pris en charge et comment.

+0

Il manque juste une mention supplémentaire pour amplifier :: interprocess :: interprocess_semaphore – moala

0

Si votre système d'exploitation prend en charge les signaux, vous pouvez déverrouiller un mutex à partir d'un gestionnaire de signal et envoyer le signal du processus A dès que vous avez terminé la tâche.

Le processus B attendrait un mutex ou un autre outil de synchronisation et A fonctionnerait sur quoi que ce soit, puis lorsque le signal USR1 finit et le gestionnaire USR1 dans le processus B déverrouille l'outil de synchronisation correspondant.

+0

Il semble que c'est POSIX; avez-vous vu cela adapté à Windows? – moala

+0

Je ne sais pas si vous pouvez utiliser correctement les signaux dans Windows, mais je sais que vous avez d'autres choix, comme les événements Windows, ne les ont pas utilisés. –

+0

Non, il n'existe pas de signaux posix fiables sur Windows ... – neuro

0

Le plus commun est d'utiliser select()/poll(). Les deux peuvent vérifier plusieurs descripteurs de fichiers s'il y a des entrées disponibles. Les deux reçoivent un paramètre de délai d'attente - cela permettra d'éviter l'attente occupée, ce qui peut consommer 100% CPU. C'est une solution très appropriée pour les petites et moyennes applications.

Une autre approche consiste à effectuer l'interrogation dans un thread séparé.

Si vous allez développer une grande application, il vaut mieux regarder vers ACE framework ou boost. Ces frameworks sont des solutions multi plates-formes, bien conçues et bien testées.

+0

Merci pour votre réponse, mais je voulais dire "sans B faire n'importe quel sondage". Peut-être que select() est plus approprié? – moala

+0

La seule chose que je puisse faire est de signaler (signal() sous Linux), mais d'après mon expérience, cette solution n'est pas appropriée pour une charge élevée. Le signal Linux annulera également les appels système (erreur EINTR), ce qui compliquera inutilement votre programme. Appeler select()/poll() avec le délai d'attente zéro, vérifiera simplement s'il y a quelque chose à lire. Après cela, vous pouvez continuer avec d'autres tâches. – dimba

+0

Aucun signal sous Windows ... – neuro

1

EDIT: Je par erreur pensé que vous aviez besoin de synchronisation inter fil RÉVISÉE pour IPC

Je pense que vous avez besoin de quelque chose comme les événements waitable.

Sous Windows, vous pouvez utiliser CreateEvent() pour créer (ou obtenir un) événement nommé, réinitialisation automatique. Lorsque le processus A termine le traitement, il doit appeler SetEvent(), tandis que le processus B doit appeler WaitForSingleObject() pour qu'il se mette en veille jusqu'à la fin (ou le dépassement du délai).

Alternativement, vous pouvez utiliser sémaphores créé par CreateSemaphore(), initialisées à 0. traiter des signaux A la fin en appelant ReleaseSemaphore(), alors que le procédé B utilise à nouveau WaitForSingleObject() à attendre la fin. Sous Linux et OS X, vous pouvez utiliser des sémaphores pour un effet similaire. utilisez sem_open() pour créer un sémaphore nommé, avec 0 comme valeur initiale.

Lorsque le processus A est terminé, il doit appeler sem_post() pour incrémenter le sémaphore, tandis que le processus B doit appeler sem_wait() pour se terminer jusqu'à la fin.

NOTE: la méthode sémaphores peut permettre à plusieurs complétions à signaler, vous devez gérer cela en fixant un nombre maximal sous Windows, ou le contrôle de la valeur ETM actuelle pour la santé mentale avec sem_getvalue()


Je pense variables de condition correspondent à ce que vous essayez de faire, voici un exemple qui fonctionne sur Linux et Mac OS X

#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); 
} 

Sous Windows, vous pouvez utiliser pthreads-win32, ou variables de condition natives sous Vista, voir la page MSDN Condition Variables pour plus d'informations.

Références:

+0

La réponse ne gère pas la partie inter processus. Je n'ai pas utilisé intensivement pthread-win32, vérifiez les problèmes de compatibilité – neuro

+0

ah, j'ai lu cela comme un problème inter-thread. Je vais réviser la réponse plus tard – Hasturkun

0

Eh bien, à mon avis et de l'expérience, la meilleure façon de le faire de manière portable et simple est d'utiliser des prises. De plus, vous avez la possibilité d'avoir les deux processus sur une machine différente (si nécessaire). De plus, vous pouvez étendre la communication pour gérer plus de synchro.

Si vous ne voulez pas interroger, utilisez un thread qui attend un message synchro sur un socket. Vous avez lu le socket d'une manière bloquante. Lorsque vous recevez le message, vous utilisez une synchronisation multithread standard pour gérer votre synchronisation. Dans votre cas, B devrait attendre jusqu'à la fin de A, il vous suffit de lire de manière bloquante dans votre processus.

Pour être portable, utilisez une bibliothèque de prises portable telle que boost ou ptypes ou autre.

Questions connexes