Développement multiplateforme (Linux) basé sur VS2019 C++ (1.5) - mémoire partagée

Introduction

        Dans l'apprentissage du pipeline précédent, nous avons utilisé des canaux nommés pour générer deux fichiers .fifo. Si les utilisateurs ne comprennent pas la technologie, ils peuvent les supprimer s'ils pensent que ce fichier est inutile. De plus, comme le maximum de données qu'un canal (qu'il s'agisse d'un canal nommé ou d'un canal anonyme) peut contenir est limité (65 535 octets), vous continuez à écrire des données dans le canal, et si vous dépassez cette capacité, le canal peut être endommagé. (Tout comme la quantité d'eau qu'un tuyau d'eau peut transporter est limitée, et il peut éclater s'il dépasse une certaine pression d'eau), donc en résumé, le tuyau est facile à supprimer par erreur, et la capacité du tuyau a une limite supérieure. Ensuite, l'étape suivante implique la mémoire partagée.

2. Présentation de la mémoire partagée

        La mémoire partagée est une plage d'adresses spéciale créée par IPC pour un processus qui apparaîtra dans l'espace d'adressage du processus. D'autres processus peuvent "lier" le même segment de mémoire partagée dans leur propre espace d'adressage. Comme indiqué ci-dessous

① La mémoire partagée dans la figure ci-dessus peut être créée par l'un des processus de A ou B. Mais il n'appartient à aucun processus (ni à A ni à B), il appartient au système d'exploitation lui-même.

② Les processus A et B peuvent accéder à l'adresse de la mémoire partagée comme s'ils étaient alloués par malloc.

③ Si le processus A écrit des données dans cette mémoire partagée, les modifications seront immédiatement vues par les autres processus qui ont accès à la même mémoire partagée, comme le processus B ici.

        Il peut être imaginé comme un vélo partagé et un trésor de recharge partagé en réalité. Premièrement, aucun de ces éléments n'appartient à l'utilisateur ; deuxièmement, tout le monde a le droit de l'utiliser ; enfin, si l'utilisateur précédent l'a cassé et que le deuxième utilisateur l'a utilisé, alors son état a été cassé la dernière fois. Pour être plus précis, si la banque d'alimentation partagée utilisée par l'utilisateur précédent utilise 30 % de la puissance, alors si ce dernier l'utilise immédiatement, seulement 70 % de la puissance est disponible. la banque d'alimentation n'a pas été chargée

        Alors pour faire simple, le partage a les trois caractéristiques suivantes : cette chose ne vous appartient pas ; n'importe qui peut l'utiliser ; cette dernière personne pourra certainement voir les résultats des opérations de la première personne.

        Revenons au concept de mémoire partagée, c'est-à-dire que cette mémoire n'appartient à aucun processus ; tous les processus peuvent utiliser cette mémoire ; si un processus modifie la mémoire, les autres processus peuvent voir le résultat de l'opération.

Vous pouvez afficher la mémoire partagée, les files d'attente de messages et les sémaphores via la commande ipcs. Les signaux et les canaux appartiennent à un certain espace de processus, mais ces trois appartiennent au système d'exploitation lui-même, et peu importe que le processus existe ou non. Autrement dit, ces trois choses sont indépendantes du processus. Si le processus n'est pas ouvert, la mémoire partagée peut toujours exister (comme illustré dans la figure ci-dessous).

ipcrm -m shmid supprime la mémoire partagée de l'identifiant spécifié

ipcm -a supprime toute la mémoire partagée créée, les sémaphores, etc. (sauf root)

 3. Fonction de mémoire partagée

1. fonction shmget - créer

Rôle : utilisé pour créer de la mémoire partagée

原型:int shmget(key_t key,size_t size, int shmflg);

Description du paramètre :

  • key : le nom du segment de mémoire partagée
  • taille : taille de la mémoire partagée
  • shmflg : se compose de neuf drapeaux d'autorisation (lecture, écriture, exécution - 0777), l'utilisation est la même que le drapeau de mode utilisé lors de la création du fichier, mais umask(0) n'est pas requis

Valeur de retour : si la mémoire partagée est créée avec succès, elle renvoie un entier non négatif, c'est-à-dire le code d'identification (shm_id) de la mémoire partagée ; si elle échoue, elle renvoie "-1" 

Remarque : Cette fonction a deux significations : si elle n'existe pas, créez-la ; si elle existe (jugée par la clé), elle ne fonctionne pas

2, fonction shmat - connexion

Fonction : Lorsque le segment de mémoire partagée vient d'être créé, aucun processus ne peut encore y accéder. Afin d'établir un canal d'accès à ce segment de mémoire partagée, nous devons le connecter à l'espace d'adressage de notre propre processus (comme partager un vélo pour utiliser après avoir scanné le code pour payer)

Exemple : void* shmat(int shm_id, const void *shm_addr, int shmflg);

Description du paramètre :

  • shm_id : identifiant de la mémoire partagée renvoyé par shmget
  • shm_addr : l'adresse où la mémoire partagée doit être placée lorsqu'elle est connectée au processus en cours
  • shmflg est un ensemble d'indicateurs qui sont associés par un OU au niveau du bit. Ses deux valeurs possibles sont SHM_RND et SHM_RDONLY

Valeur de retour : si l'appel réussit, il renvoie un pointeur, qui pointe sur le premier octet de la mémoire partagée ; s'il échoue, il renvoie "-1" (void* signifie que n'importe quel type peut être stocké , car il se connecte simplement et ne sait pas de quel type il s'agit.)

3, fonction shmdt - déconnecter

Fonction : séparer la mémoire partagée du processus en cours (comme l'action de retour d'un vélo partagé)

Prototype : int shmdt(const void *shm_addr);

Description du paramètre : shm_addr : le pointeur d'adresse renvoyé par shmat

Valeur de retour : Si l'opération réussit, elle retournera "0", et si elle échoue, elle retournera "-1"

Quitter la mémoire partagée ne signifie pas la supprimer, c'est juste que le processus en cours ne peut plus y accéder.

4. fonction shmctl - supprimer

Fonction : fonction de contrôle de la mémoire partagée (généralement non utilisée, car les données peuvent être partagées et peuvent être écrasées , pas besoin de les supprimer)

Exemple : int shmctl(int shm_id,int command,struct shmid_ds *buf);

Description du paramètre :

  • shm_id : code d'identification de la mémoire partagée renvoyé par shmget
  • commande : Action à entreprendre (trois valeurs : IPC_STAT, IPC_SET, IPC_RMID)
  • buf : pointe vers une structure de données qui contient l'état du mode et les droits d'accès de la mémoire partagée

Valeur de retour : Si l'opération réussit, elle retournera "0", et si elle échoue, elle retournera "-1"

 Opérations de mémoire :

  • memset initialise généralement la mémoire nouvellement appliquée (vide - fonction bzero)
  • copie de la mémoire memcpy, il suffit de copier les données, les données d'origine ne seront pas vidées

4. Exemples

        Créez deux applications, une pour la lecture et une pour l'écriture

1.Code

#include <iostream>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <string.h>
using namespace std;

//写端

typedef struct student
{
	char stuid[10];
	char name[20];

}STU;
int main()
{
	void* shmaddr = NULL;
	int shmid = 0;

	STU stu1 = { "1001","zqw"};
	//创建
	shmid = shmget((key_t)1001,2048,IPC_CREAT|0777);

	if (shmid == -1)
	{
		perror("shmget  error");
	}
	else
	{
		//连接共享内存 获取到共享内存的首地址shmaddr
		shmaddr = shmat(shmid,NULL,0);

		//写入数据  = 内存拷贝
		memcpy(shmaddr, &stu1,sizeof(STU));

		/*cout <<"res_stu  id" << res_stu.stuid<< endl;
		cout << "res_stu  name" << res_stu.name << endl;*/

		//断开共享内存的连接
		shmdt(shmaddr);
	}

	return 0;
}

//读端

typedef struct student
{
	char stuid[10];
	char name[20];

}STU;
int main()
{
	void* shmaddr = NULL;
	int shmid = 0;

	STU res_stu = { 0 };
	//创建
	shmid = shmget((key_t)1001, 2048, IPC_CREAT | 0777);

	if (shmid == -1)
	{
		perror("shmget  error");
	}
	else
	{
		//连接共享内存 获取到共享内存的首地址
		shmaddr = shmat(shmid, NULL, 0);

		//读取数据  = 内存拷贝
		memcpy(&res_stu, shmaddr, sizeof(STU));

		cout << "读端  id = " << res_stu.stuid << endl;
		cout << "读端  name = " << res_stu.name << endl;

		//断开共享内存的连接

		shmdt(shmaddr);
	}

	return 0;
}

2. Résultats en cours d'exécution 

  • Étant donné que les données ne sont pas modifiées, effacées, etc. du côté lecture, il s'agit simplement d'une simple copie, de sorte que les données de la mémoire partagée sont toujours là et que le résultat de lectures multiples est toujours le même.
  • Lorsque le processus se termine, la mémoire partagée est toujours là, indiquant que la mémoire partagée est directement gérée par le système d'exploitation plutôt que par le processus.
  • La mémoire partagée est suffisante pour être utilisée, elle occupera de la mémoire après la création jusqu'à ce que vous la supprimiez manuellement

 Veuillez indiquer la source

Développement multiplateforme (Linux) basé sur VS2019 C++ (1.5) - mémoire partagée

Je suppose que tu aimes

Origine blog.csdn.net/hml111666/article/details/123697406
conseillé
Classement