2010-12-04 65 views
0

Je vais implémenter un programme où un processus parent lit un fichier texte et envoie les données qu'il lit dans un tampon de mémoire partagée qui va être lu par certains processus enfants. Tout ce travail sera médiatisé par des sémaphores. Supposons que le parent va lire un caractère à la fois à partir du fichier et que le tampon de mémoire partagée contient 5 emplacements.Problème de producteur/consommateur

Au début, je pensais seulement avoir 2 sémaphores:

writeSemaphore, initialisé à 5, est le sémaphores qui indique si l'auteur est autorisé à écrire dans la mémoire tampon. quand il descendra finalement à 0, le processus parent sera bloqué jusqu'à ce que l'un des enfants le déverrouille (après avoir lu un bloc).

readSemaphore, initialisé à 0, est le sémaphore qui indique si l'un des lecteurs est autorisé à lire dans le tampon. Mais maintenant que je pense à cela, cela ne m'empêcherait pas d'avoir 2 consommateurs accédant à la mémoire partagée en même temps. Je dois l'empêcher. J'ai donc introduit un troisième sémaphore:

allowedToRead qui est 1 ou 0, qui permet ou bloque l'accès aux processus enfants.

Voici le code pseudo pour les enfants et les parents:

enfant:

while (something) { 
    wait(readSemaphore) 
    wait(allowedToRead) 
    <<read from shared memory>> 
    post(allowedToRead) 
    post(writeSemaphore) 
} 

Parent:

while (something) { 
    wait(writeSemaphore) 
    <<writes to shared memory>> 
    post(allowedToRead) 
} 

est mon raisonnement correct?

Merci

+0

Vous pourriez trouver Boost.Interprocess utile pour vous épargner un peu de lourdeur dans la gestion de la mémoire partagée. Il y a des constructions directes en continu de processus à processus décrites ici: http://www.boost.org/doc/libs/1_45_0/doc/html/interprocess/streams.html –

+0

Ceci est pour l'école, donc pas de boost pour moi. –

Répondre

1

Khachik est la moitié droite. Il a peut-être raison, mais sa description n'est pas aussi claire qu'elle pourrait l'être.

Tout d'abord, lorsque vous avez le parent allowedToRead vous signifiez probablement pour qu'il affiche readSemaphore. En second lieu, votre code permet au parent d'écrire en même temps qu'un enfant est en train de lire. Vous dites que vous avez 5 emplacements. Si le parent écrit dans un emplacement différent de celui que l'enfant lit, alors je suppose que c'est correct, mais comment l'enfant détermine-t-il où lire? Utilise-t-il les mêmes variables que celles utilisées par le parent pour déterminer où écrire? Vous avez probablement besoin d'une protection supplémentaire là-bas. Après tout, je suppose que les différents enfants lisent tous des emplacements différents, donc si vous devez les empêcher de marcher sur les orteils d'un autre, vous devrez faire la même chose pour le parent.

Troisièmement, j'aurais utilisé un mutex au lieu d'un sémaphore pour allowedToRead.

Quatrièmement, qu'est-ce qui détermine quel enfant lit quelles données ou est-il censé être le premier arrivé premier servi comme des cochons à un seau de slops?

Si la mémoire partagée a 5 emplacements indépendants, alors je serais enclin à ajouter une variable "next read" et "next write". Protégez ces deux variables avec un mutex dans le producteur et les consommateurs, puis utilisez les sémaphores juste pour bloquer/déclencher la lecture et l'écriture comme vous le faites déjà. Si ce n'était pas un exercice scolaire, vous pourriez faire mieux en utilisant une seule variable de condition attachée au mutex que j'ai mentionné. Quand il est signalé, le parent vérifie s'il peut écrire et les enfants vérifient s'ils peuvent lire. Lorsqu'une lecture ou une écriture se produit, signalez globalement la variable de condition pour réveiller tout le monde afin de vérifier leurs conditions. Cela a l'avantage que si vous avez des emplacements de mémoire tampon indépendants, vous pouvez en toute sécurité et en même temps avoir plusieurs consommateurs consommant en même temps.

1

No.

  1. l'écrivain doit libérer readSemaphore quand il écrire une unité d'information;
  2. le rédacteur doit acquérir le verrou allowedToRead (0,1 sémaphore est un verrou/mutex) avant d'écrire dans la mémoire partagée pour éviter les conditions de course.

Pour simplifier: considérer deux fonctions read_shared_memory, write_shared_memory, qui sont à lire et à écrire de/vers la mémoire partagée, respectivement, et à la fois l'acquisition/libérant le même verrou avant la lecture/écriture.

Le producteur acquiert un sémaphore d'écriture, appelle la fonction d'écriture, libère le sémaphore lu. Le consommateur acquiert le sémaphore, appelle la fonction de lecture, libère le sémaphore d'écriture. Bien sûr, cela peut être mis en œuvre sans fonctions de lecture/écriture, ils sont simplement pour simplifier l'accès atomique à la mémoire partagée. Une section critique peut être implémentée à l'intérieur des boucles produire/consommer sans fonctions supplémentaires.

Wikipedia Il décrit en plus de manière scientifique :)

+0

Je ne comprends toujours pas quel est le problème avec ma mise en œuvre. Quelle condition de course pourrais-je obtenir? Lorsque le producteur écrit, les consommateurs attendent. Lorsque les consommateurs lisent, un seul d'entre eux peut être à la fois. –

+0

@devoured avez-vous lu l'article wikipedia? – khachik

+0

il se plaint seulement des conditions de course avec plusieurs producteurs - j'en ai seulement 1. –