begin process at 2012 05 27 21:12:05
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Applications Linux

 > UTILISATION SIMPLE D'UNE MÉMOIRE PARTAGÉE SOUS LINUX (SHM)

UTILISATION SIMPLE D'UNE MÉMOIRE PARTAGÉE SOUS LINUX (SHM)


 Information sur la source

Note :
10 / 10 - par 1 personne
10,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Applications Linux Classé sous :mémoire, partagée, shmget, shmat, ipc Niveau :Initié Date de création :09/02/2007 Vu :30 276

Auteur : triskell2000

Ecrire un message privé
Site perso
Commentaire sur cette source (4)
Ajouter un commentaire et/ou une note

 Description

Ceci est juste un exemple simple de l'utilisation d'une mémoire partagée entre 2 processus (au sens de 2 exécutables bien distincts (pas de thread)) sous linux. Je me sers de la librairie sys/shm.h. Cet exemple est compilable (pour ma part avec g++).
Il y a donc 2 programmes:
- Le programme A, qui crée une mémoire partagée et qui va aller inscrire une structure dans cette mémoire. Un des champs de cette structure est mis à jour en permanence.
- Le programme B attache la mémoire partagée créée par A, son propre processus, puis va lire les données contenues dans la structure crée par A.

Ceci est donc un exemple basic de l'utilisation de mémoire partagée, mais n'ayant pas trouvé d'exemple simple, je le poste ici en espérant qu'il évitera à beaucoup des heures de galère...



Source

  • // code source du processus A
  • #include <sys/types.h>
  • #include <sys/ipc.h>
  • #include <sys/shm.h>
  • #include <math.h>
  • #include <iostream>
  • using namespace std;
  • #define CLEF 12345 // je définis une clef au hasard
  • // Je définis une structure quelconque qui comporte un entier et un double.
  • typedef struct
  • {
  • int a;
  • double b;
  • }structure_partagee;
  • int main()
  • {
  • // variable quelconque qui me sers pour un compteur plus bas...
  • int i = 0;
  • int mem_ID; // identificateur du segment de mémoire partagée associé à CLEF
  • void* ptr_mem_partagee; // pointeur sur l'adresse d'attachement du segment de mémoire partagée
  • // J'instancie une structure "structure_partagee" et je l'appelle Data.
  • structure_partagee Data;
  • if ((mem_ID = shmget(CLEF, sizeof(Data), 0666 | IPC_CREAT)) < 0) // je crée un nouveau segment mémoire de taille "taille de ma structure data" octets, avec des droits d'écriture et de lecture
  • {
  • perror("shmget"); // et je m'assure que l'espace mémoire a été correctement créé
  • exit(1);
  • }
  • if ((ptr_mem_partagee = shmat(mem_ID, NULL, 0)) == (void*) -1) // J'attache le segment de mémoire partagée identifié par mem_ID au segment de données du processus A dans une zone libre déterminée par le Système d'exploitation
  • {
  • perror("shmat"); // et je m'assure que le segment de mémoire a été correctement attaché à mon processus
  • exit(1);
  • }
  • // J'alloue des valeurs aux variables de ma structure
  • Data.a = 2;
  • Data.b = 2.6544;
  • // je mets à jour ces valeurs en mémoire partagée. ptr_mem_partagee est un pointeur de void. Je le caste pour qu'il devienne un pointeur de "structure_partagee" Et je vais écrire ma structure Data à l'adresse pointée par ce pointeur.
  • *((structure_partagee*)ptr_mem_partagee) = Data;
  • // je vais modifier en permanence le champ a de ma structure et le mettre à jour, le processus B lira la structure Data.
  • while(1)
  • {
  • Data.a = i;
  • *((structure_partagee*)ptr_mem_partagee) = Data;
  • i++;
  • if(i == 100000000) // je remets à 0 de temps en temps...
  • i = 0;
  • }
  • // Une fois sortie de la boucle (bon OK là elle est infine), je détache mon segment mémoire de mon processus, et quand tous les processus en auront fait autant, ce segment mémoire sera détruit.
  • shmdt(ptr_mem_partagee);
  • // je quitte le programme
  • return 0;
  • }
  • // code source du processus B
  • #include <sys/types.h>
  • #include <sys/ipc.h>
  • #include <sys/shm.h>
  • #include <iostream>
  • using namespace std;
  • #define CLEF 12345 // !!je définis la même clef que celle du processus A!!
  • // Je crée la même structure que dans le programme A.
  • // Les noms des variables n'ont rien à voir avec le programme A, seule la structure est importante.
  • typedef struct
  • {
  • int c;
  • double d;
  • }structure_partagee_B;
  • int main()
  • {
  • // je déclare des variables aptes à recevoir les variables de la structure "structure_partagee" définie dans le processus A
  • int var1;
  • double var2;
  • int mem_ID_B; // identificateur du segment de mémoire partagée associé à CLEF (là encore le nom de cette variable n'a rien à voir avec celle du programme A mais son contenu sera évidemment identique)
  • void* ptr_mem_partagee_B; // adresse d'attachement du segment de mémoire partagée (idem)
  • // J'instancie une structure "structure_partagee_B" et je l'appelle Data_B. Cela me sert uniquement à connaitre la taille de ma structure. Pour bien faire, il faudrait évidemment déclarer cette structure dans un .h qui serait inclu dans A et dans B avec la clef, de façon à garder la cohérence entre les 2 programmes
  • structure_partagee_B Data_B;
  • if ((mem_ID_B = shmget(CLEF, sizeof(Data_B), 0444)) < 0) // Je cherche le segment mémoire associé à CLEF et je récupère l'identificateur de ce segment mémoire... J'attribue des droits de lecture uniquement
  • {
  • perror("shmget"); // et je m'assure que l'espace mémoire a été correctement créé
  • exit(1);
  • }
  • if ((ptr_mem_partagee_B = shmat(mem_ID_B, NULL, 0)) == (void*) -1) // J'attache le segment de mémoire partagée identifié par mem_ID_B au segment de données du processus B dans une zone libre déterminée par le Système d'exploitation
  • {
  • perror("shmat"); // et je m'assure que le segment de mémoire a été correctement attaché à mon processus
  • exit(1);
  • }
  • // j'affiche le contenu des variables inscrites par A dans la mémoire partagée
  • while(1) {
  • // je caste ptr_mem_partagee_B pour qu'il devienne un pointeur de structure_partagee_B et j'affiche le champ c (ou d) de la structure pointée par ((structure_partagee_B*)ptr_mem_partagee_B)
  • var1 = ((structure_partagee_B*)ptr_mem_partagee_B)->c;
  • var2 = ((structure_partagee_B*)ptr_mem_partagee_B)->d;
  • // j'affiche le contenu des champs de la structure l'un à côté de l'autre, et je reviens au début de la ligne.
  • cout << "data.a = " << var1 ;
  • cout << " data.b = " << var2 << "\r";
  • }
  • // Je détruis le segment (le segment n'est pas détruit tant qu'au moins un processus est lié au segment)
  • shmdt(ptr_mem_partagee_B);
  • // je quitte le programme
  • return 0;
  • }
//	code source du processus A
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <math.h>
#include <iostream>
using namespace std;

#define CLEF 12345 // je définis une clef au hasard

//	Je définis une structure quelconque qui comporte un entier et un double.
typedef struct
{
	int a;
	double b;
}structure_partagee;

int main()
{
	//	variable quelconque qui me sers pour un compteur plus bas...
	int i = 0;

	int mem_ID; //	identificateur du segment de mémoire partagée associé à CLEF
	void* ptr_mem_partagee; //	pointeur sur l'adresse d'attachement du segment de mémoire partagée

	//	J'instancie une structure "structure_partagee" et je l'appelle Data.
	structure_partagee Data;

	if ((mem_ID = shmget(CLEF, sizeof(Data), 0666 | IPC_CREAT)) < 0)	//	je crée un nouveau segment mémoire de taille "taille de ma structure data" octets, avec des droits d'écriture et de lecture
	{
		perror("shmget");											//	et je m'assure que l'espace mémoire a été correctement créé
		exit(1);
	}

	if ((ptr_mem_partagee = shmat(mem_ID, NULL, 0)) == (void*) -1)	//	J'attache le segment de mémoire partagée identifié par mem_ID au segment de données du processus A dans une zone libre déterminée par le Système d'exploitation
	{
		perror("shmat");											//	et je m'assure que le segment de mémoire a été correctement attaché à mon processus
		exit(1);
	}
	
	//	J'alloue des valeurs aux variables de ma structure
	Data.a = 2;
	Data.b = 2.6544;

	//	je mets à jour ces valeurs en mémoire partagée. ptr_mem_partagee est un pointeur de void. Je le caste pour qu'il devienne un pointeur de "structure_partagee" Et je vais écrire ma structure Data à l'adresse pointée par ce pointeur.
	*((structure_partagee*)ptr_mem_partagee) = Data;
	
	//	je vais modifier en permanence le champ a de ma structure et le mettre à jour, le processus B lira la structure Data.
	while(1)
	{
		Data.a = i;
		*((structure_partagee*)ptr_mem_partagee) = Data;
		i++;
		if(i == 100000000)	//	je remets à 0 de temps en temps...
			i = 0;
	}

	//	Une fois sortie de la boucle (bon OK là elle est infine), je détache mon segment mémoire de mon processus, et quand tous les processus en auront fait autant, ce segment mémoire sera détruit.
	shmdt(ptr_mem_partagee);

	//	je quitte le programme
	return 0;
}



//	code source du processus B
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <iostream>
using namespace std;

#define CLEF 12345 // !!je définis la même clef que celle du processus A!!

//	Je crée la même structure que dans le programme A.
//	Les noms des variables n'ont rien à voir avec le programme A, seule la structure est importante.
typedef struct
{
	int c;
	double d;
}structure_partagee_B;

int main()
{
	//	je déclare des variables aptes à recevoir les variables de la structure "structure_partagee" définie dans le processus A
	int var1;
	double var2;

	int mem_ID_B; //	identificateur du segment de mémoire partagée associé à CLEF (là encore le nom de cette variable n'a rien à voir avec celle du programme A mais son contenu sera évidemment identique)
	void* ptr_mem_partagee_B; //	adresse d'attachement du segment de mémoire partagée (idem)

	//	J'instancie une structure "structure_partagee_B" et je l'appelle Data_B. Cela me sert uniquement à connaitre la taille de ma structure. Pour bien faire, il faudrait évidemment déclarer cette structure dans un .h qui serait inclu dans A et dans B avec la clef, de façon à garder la cohérence entre les 2 programmes
	structure_partagee_B Data_B;

	if ((mem_ID_B = shmget(CLEF, sizeof(Data_B), 0444)) < 0)	//	Je cherche le segment mémoire associé à CLEF et je récupère l'identificateur de ce segment mémoire... J'attribue des droits de lecture uniquement
	{
		perror("shmget");											//	et je m'assure que l'espace mémoire a été correctement créé
		exit(1);
	}
	if ((ptr_mem_partagee_B = shmat(mem_ID_B, NULL, 0)) == (void*) -1)	//	J'attache le segment de mémoire partagée identifié par mem_ID_B au segment de données du processus B dans une zone libre déterminée par le Système d'exploitation
	{
		perror("shmat");											//	et je m'assure que le segment de mémoire a été correctement attaché à mon processus
		exit(1);
	}

	//	j'affiche le contenu des variables inscrites par A dans la mémoire partagée
	while(1) {
		//	je caste ptr_mem_partagee_B pour qu'il devienne un pointeur de structure_partagee_B et j'affiche le champ c (ou d) de la structure pointée par ((structure_partagee_B*)ptr_mem_partagee_B)
		var1 = ((structure_partagee_B*)ptr_mem_partagee_B)->c;
		var2 = ((structure_partagee_B*)ptr_mem_partagee_B)->d;
		//	j'affiche le contenu des champs de la structure l'un à côté de l'autre, et je reviens au début de la ligne.
		cout << "data.a = " << var1 ;
		cout << " data.b = " << var2 << "\r";
	}

	//	Je détruis le segment (le segment n'est pas détruit tant qu'au moins un processus est lié au segment)
	shmdt(ptr_mem_partagee_B);

	//	je quitte le programme
	return 0;
}

 Conclusion

Je ne reviens pas sur le mécanisme du programme. Le mécanisme est bien expliqué sur internet et les sources sont très commentées...


 Sources de la même categorie

Source avec Zip TRAITEMENT D'IMAGE PGM par Jios
Source avec une capture COLORIMÈTRE NUMÉRIQUE LINUX par valchek
Source avec Zip TRAITEMENTS D'IMAGES AU FORMAT PGM AVEC LES ALGORITHMES DE C... par lemout
Source avec Zip ALGORITHME ACO INTERFACE GTK par RyBeN
Source avec Zip COMPRESSER SES SAUVEGARDES SMSBACKUPRESTORE (ANDROID) EN C A... par ThalLab

 Sources en rapport avec celle ci

[DEV-C++] CALCUL DE LA RACINE CARRÉE D'UN RÉEL par Jhep
PROCESS DUMPER par lilxam7
Source avec Zip LIBRAIRIE POUR ÉVITER LES FUITES MEMOIRES par glipper
SUPRIMER SHM SEM MSGQUEUE par Shibo_Sources
MODIFIER UN PROCESSUS EN MÉMOIRE par lilxam

Commentaires et avis

Commentaire de Shibo_Sources le 22/11/2007 17:16:27

Bon tutorial, simple et efficace.

Cependant, après avoir détaché la shared memory, ne faudrait-il pas la supprimer avec:
shmctl(mem_ID, IPC_RMID, 0);

Je ne sais pas si sous linux l'IPC gére automatiquement la suppression mais sous Sun il est nécessaire de le faire, enfin il me semble.

Une question me turlupine le bulbe aussi:
Pourquoi avoir utilisé un pointeur void et s'amuser à le caster alors qu'on aurais pu définir un pointeur de structure "structure_partagee *" ? Es-ce pour une question d'optimisation?

Sinon, rien à redire.

Commentaire de David36250 le 07/08/2008 17:55:46 10/10

Très bon tutorial, explique très clairement une chose plutot obscure d'après les Man...
pour une fois que mmap n'est pas associé à shm, c'est plus simple a comprendre
merci à toi.

Commentaire de xMatko le 11/06/2009 19:21:00

"...en espérant qu'il évitera à beaucoup des heures de galère..."

c'est gagné ;) Merci beaucoup pour cette source tuto

Commentaire de bigbe le 08/06/2011 09:09:21

Merci pour cet exemple, 30 mn de travail autour, j'ai bien compris et tout fonctionne, bravo !

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

conseil pour récupérer des messages [ par lamalice83 ] Salut à tous,j'ai 2 programmes qui tournent en //, l'un en cpp l'autre en vbnet.Celui en cpp, composé de 4 threads, enregistre des valeurs et stocke d Passer une instance de classe dans une mémoire partagée ?? [ par vinvay ] Comment puis-je passer une instance de classe dans une shared memory, sachant que cette classe contient une structure. J'arrive, dans le deuxième prog mémoire partagée sécurisé ou pas ? [ par HeavenForsaker ] Bonjour,J'utilise la fonction CreateFileMapping pour partager des variables entre différentes applications, pour accéder aux variables de la mémoire p Comment visualiser une mémoire partagée? [ par sins ] <link rel="Fi Erreur d'application c++ [ par kebab38 ] Bonjour, j'intervient sur une modification d'un programme assez long en C++, mais avant de commencer je doit resoudre une erreur d'application qui int please HELP !!! [ par toutouti ] Bonsoir à tous,je suis doctorante et j'ai un gros soucis avec mon pg en C.Il se trouve que je fais des allocations mémoire dynamique afin de pouvoir l Copier une texture vers une autre en mémoire systeme ? [ par supergrey ] Bonjour, j'ai repris une source qui crée une dll directx 9, en gros c'est pour un hook. Donc un programme qui utilise directx charge des textures et m Gestionnaire de la mémoire [ par BabGirl ] Bonjour à tous !Pourriez-vous me guider pour créer un petit gestionnaire de la mémoire. Ce petit gestionnaire doit connaître les parties libres et occ Organisation de la mémoire [ par KurpeusLondon ] Désolé une petite question de plus pour la forme:)Je comprends pas comment est organisé la mémoire lors d'un malloc et compagnie : je m'explique.J'ai Mémoire allouée à un executable [ par smasher81 ] Bonjour, bonsoir!J'aimerai savoir si c'est possible de savoir qu'elles sont les adresses mémoires alloués à des programmes executé en même temps que m


Nos sponsors


Sondage...

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,530 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales