7
votes

Comment puis-je stocker et récupérer une structure dans une zone de mémoire partagée en C

Pour une affectation UNI, j'ai besoin de créer une liste circulaire de 10 noms de fichiers jusqu'à 10 noms de fichiers, puis de les stocker dans une zone de mémoire partagée, de sorte que 2 processus enfants peuvent lire / écrire à la liste (à l'aide d'un sémaphore pour contrôler l'accès. ). Le problème est que je suis un novice total de C et je me sens la perte et le désespoir parce que c'est totalement hors de ma profondeur. J'ai besoin d'aide pour "remplir les trous" de mes connaissances.

En ce moment, je me concentre simplement sur un problème à la fois et, actuellement, je n'essaie que de recevoir ma liste circulaire dans la zone de mémoire partagée .

Jusqu'à présent, j'ai: xxx

comme mon struct qui conserve la référence au fichier suivant (f_link). De cette façon, je peux simplement appeler -> F_Link pour obtenir l'élément suivant dans la liste et où le 10ème élément aura simplement son f_link dirigé vers le 1er. Ma raison pour que cela puisse faire cela, c'est que je puisse simplement traverser la liste sans itérateur (et je n'ai jamais à vérifier la fin de la liste comme je le ferais avec un tableau).

Je sais aussi que j'ai besoin que j'ai besoin de utiliser shmget pour obtenir la zone de mémoire, et je le comprends, je passe shmget une touche, une taille et un drapeau (que je ne reçois pas) et qu'il renvoie un identifiant Dans le type d'un int.

Donc, ma question est 2 fois. Comment puis-je stocker ma liste liée à la zone de mémoire partagée - et comment l'accéder à partir de la zone de mémoire partagée?


0 commentaires

4 Réponses :


2
votes

Vous appelez shmat (identifiant, null, 0) , récupérez un pointeur à l'emplacement que la mémoire partagée a été mappée dans votre processus. Créez votre objet à cet emplacement ou memcpy / Memmove à cet emplacement.

Vous trouverez probablement Guide IPC UNIX de Beej's UNIX utile, il contient une section spécifiquement sur la mémoire partagée .


0 commentaires

1
votes

Pour le drapeau, vous devez spécifier au moins IPC_Create si vous souhaitez affecter un nouveau segment de mémoire partagé, sinon, il apparaîtra de SEGEMNT existant et d'échouer s'il n'en trouve pas un.

Deuxièmement, lorsque le segment de mémoire partagé est un bloc de mémoire contigu, vous devez pouvoir stocker toutes les 10 structures File_Entry ensemble (ou allouer 10 segments de mémoire partagés - Yuck!).

Vous avez donc vraiment besoin de shmeget suffisamment de mémoire pour un tableau d'au moins 10 structures de fichiers.

Enfin, le fichier et le fichier_Entry sont des noms vraiment mauvais! Utilisez quelque chose de moins générique comme my_file_ref et myfilerefenterry.


0 commentaires

2
votes

Après avoir obtenu la clé de shmget , vous devez l'utiliser pour obtenir le pointeur réel via shmat . Voici quelques échantillons: xxx

de cette façon, vous pourrez accéder à la mémoire partagée à l'aide du pointeur shm . Dans ces liens, vous pouvez voir le Manpage pour shmget et shmat :

http://linux.die.net/man/2/shmget

http://linux.die.net/man/2/shmat

et voir http://www.cplusplus.com pour une référence supplémentaire. Il contient une référence c aussi.

Je ne sais pas si j'étais assez clair, alors donnez-lui des commentaires et je vais essayer de l'éclairer pour vous, si nécessaire.

Edit: Dans ce site, vous pouvez trouver un exemple vraiment simple: http://simplestcodings.blogspot.com/2010/08/ipc-shared-Memory-Implementalation-in-c.html


0 commentaires

10
votes

shmget code> se réserve juste une certaine quantité de mémoire partagée - comme créer un fichier de taille fixe sur disque. Les drapeaux sont un masque d'autorisation (comme le mode code> code> paramètre pour Ouvrir code>) dans le bas 9 bits plus des drapeaux supplémentaires, ipc_creat code> et et Ipc_excl code>, correspondant à o_creat code> et o_excl code> pour Ouvrir code>. Pour accéder à cette mémoire, vous devez la modifier dans l'espace d'adressage de votre processus ("Joindre" IT - analogue à MMAP code> pour les fichiers). Ceci est fait en utilisant shmat code> (qui renvoie un pointeur). Vous devez ensuite allouer vos structures code> fichier code> à partir de ce pointeur. L'ensemble du processus ressemble à ceci:

int id;
FILE_entry *entries;

id = shmget(key, N * sizeof(FILE_entry), IPC_CREAT | 0644);
entries = (FILE_entry *) shmat(id, NULL, 0);

// you can now access entries as if it was a N-element array.
// to turn it into a circular list, link the entries appropriately.


6 commentaires

Si un seul processus modifie la liste et l'autre ne se lit que (et jamais en même temps) le problème du pointeur que vous avez mis en évidence au bas de votre réponse soit moins problématique?


Ce n'est pas un problème de concurrence. Les pointeurs dépendent du contexte - ils sont locaux dans l'espace d'adressage. Processus A peut configurer la liste et l'avoir mappé sur 0x1000000 (les pointeurs sont donc dans cette plage), tandis que le processus B pourrait l'avoir mappé sur 0x1100000. Si B tente de suivre les pointeurs de la zone de mémoire partagée, il s'écrasera au mieux car la plage de mémoire correspondante n'est pas du tout cartographiée, et au pire, il lira certaines autres données sans rapport aléatoires qui se produisent à cette adresse en cours. B et se comporter de manière imprévisible.


Mais si la zone de mémoire partagée est un bloc de mémoire continue statique, assurez-vous que l'adresse de la mémoire de l'octet [0] de cet espace partagé doit être la même !?


Et en plus de cela, avec la struct, j'ai défini ci-dessus, chaque article soit 287 octets long chacun (quel que soit le "nom")? Alors, pourquoi auriez-vous besoin d'un décalage lorsque vous pouvez simplement itérer ce nombre d'octets le long?


@Ash: Nope - La mémoire partagée peut être jointe à une autre plage d'adresses virtuelles dans chaque processus.


Ok, au moins au moins je suis juste à propos de la taille fixe pour chaque structure?