La memoire partagée
La mémoire partagée est une mémoire partagée entre deux ou plusieurs processus. Cependant, pourquoi avons-nous besoin de partager la mémoire ou d'autres moyens de communication?
Pour réitérer, chaque processus a son propre espace d'adressage, si un processus veut communiquer avec certaines informations de son propre espace d'adressage vers d'autres processus, alors cela n'est possible qu'avec les techniques IPC (communication inter-processus). Comme nous le savons déjà, la communication peut se faire entre des processus liés ou non.
Habituellement, la communication de processus interdépendants est effectuée à l'aide de tuyaux ou de tuyaux nommés. La communication de processus non liés (par exemple, un processus exécuté dans un terminal et un autre processus dans un autre terminal) peut être effectuée à l'aide de canaux nommés ou par des techniques IPC courantes de mémoire partagée et de files d'attente de messages.
Nous avons vu les techniques IPC des tuyaux et des canaux nommés et il est maintenant temps de connaître les techniques IPC restantes, à savoir la mémoire partagée, les files d'attente de messages, les sémaphores, les signaux et le mappage de la mémoire.
Dans ce chapitre, nous saurons tout sur la mémoire partagée.
Nous savons que pour communiquer entre deux ou plusieurs processus, nous utilisons la mémoire partagée mais avant d'utiliser la mémoire partagée ce qui doit être fait avec les appels système, voyons ceci -
Créez le segment de mémoire partagée ou utilisez un segment de mémoire partagée déjà créé (shmget ())
Attachez le processus au segment de mémoire partagée déjà créé (shmat ())
Détachez le processus du segment de mémoire partagée déjà attaché (shmdt ())
Opérations de contrôle sur le segment de mémoire partagée (shmctl ())
Examinons quelques détails des appels système liés à la mémoire partagée.
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg)
L'appel système ci-dessus crée ou alloue un segment de mémoire partagée System V. Les arguments qui doivent être passés sont les suivants -
le first argument, key,reconnaît le segment de mémoire partagée. La clé peut être une valeur arbitraire ou une valeur qui peut être dérivée de la fonction de bibliothèque ftok (). La clé peut également être IPC_PRIVATE, c'est-à-dire exécuter des processus en tant que serveur et client (relation parent et enfant), c'est-à-dire, une communication de processus inter-liés. Si le client souhaite utiliser la mémoire partagée avec cette clé, il doit s'agir d'un processus enfant du serveur. En outre, le processus enfant doit être créé une fois que le parent a obtenu une mémoire partagée.
le second argument, size, est la taille du segment de mémoire partagée arrondie au multiple de PAGE_SIZE.
le third argument, shmflg,spécifie le ou les indicateurs de mémoire partagée requis tels que IPC_CREAT (création d'un nouveau segment) ou IPC_EXCL (utilisé avec IPC_CREAT pour créer un nouveau segment et l'appel échoue, si le segment existe déjà). Vous devez également passer les autorisations.
Note - Reportez-vous aux sections précédentes pour plus de détails sur les autorisations.
Cet appel renverrait un identifiant de mémoire partagée valide (utilisé pour d'autres appels de mémoire partagée) en cas de succès et -1 en cas d'échec. Pour connaître la cause de l'échec, vérifiez avec la variable errno ou la fonction perror ().
#include <sys/types.h>
#include <sys/shm.h>
void * shmat(int shmid, const void *shmaddr, int shmflg)
L'appel système ci-dessus effectue une opération de mémoire partagée pour le segment de mémoire partagée System V, c'est-à-dire en attachant un segment de mémoire partagée à l'espace d'adressage du processus appelant. Les arguments qui doivent être passés sont les suivants -
The first argument, shmid,est l'identifiant du segment de mémoire partagée. Cet identifiant est l'identifiant de la mémoire partagée, qui est la valeur de retour de l'appel système shmget ().
The second argument, shmaddr,est de spécifier l'adresse de rattachement. Si shmaddr est NULL, le système choisit par défaut l'adresse appropriée pour attacher le segment. Si shmaddr n'est pas NULL et que SHM_RND est spécifié dans shmflg, l'attachement est égal à l'adresse du multiple le plus proche de SHMLBA (Lower Boundary Address). Sinon, shmaddr doit être une adresse alignée sur la page à laquelle la pièce jointe de mémoire partagée se produit / démarre.
The third argument, shmflg, spécifie le ou les indicateurs de mémoire partagée requis tels que SHM_RND (arrondi de l'adresse à SHMLBA) ou SHM_EXEC (permet l'exécution du contenu du segment) ou SHM_RDONLY (attache le segment à des fins de lecture seule, par défaut, il est en lecture-écriture) ou SHM_REMAP (remplace le mappage existant dans la plage spécifiée par shmaddr et continue jusqu'à la fin du segment).
Cet appel renverrait l'adresse du segment de mémoire partagée attaché en cas de succès et -1 en cas d'échec. Pour connaître la cause de l'échec, vérifiez avec la variable errno ou la fonction perror ().
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr)
L'appel système ci-dessus effectue une opération de mémoire partagée pour le segment de mémoire partagée System V consistant à détacher le segment de mémoire partagée de l'espace d'adressage du processus appelant. L'argument à passer est -
L'argument, shmaddr, est l'adresse du segment de mémoire partagée à détacher. Le segment à détacher doit être l'adresse renvoyée par l'appel système shmat ().
Cet appel renverrait 0 en cas de succès et -1 en cas d'échec. Pour connaître la cause de l'échec, vérifiez avec la variable errno ou la fonction perror ().
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
L'appel système ci-dessus effectue une opération de contrôle pour un segment de mémoire partagée System V. Les arguments suivants doivent être passés -
Le premier argument, shmid, est l'identifiant du segment de mémoire partagée. Cet identifiant est l'identifiant de la mémoire partagée, qui est la valeur de retour de l'appel système shmget ().
Le deuxième argument, cmd, est la commande pour effectuer l'opération de contrôle requise sur le segment de mémoire partagée.
Les valeurs valides pour cmd sont -
IPC_STAT- Copie les informations des valeurs actuelles de chaque membre de la structure shmid_ds dans la structure passée pointée par buf. Cette commande nécessite une autorisation de lecture sur le segment de mémoire partagée.
IPC_SET - Définit l'ID utilisateur, l'ID de groupe du propriétaire, les autorisations, etc. pointés par la structure buf.
IPC_RMID- Marque le segment à détruire. Le segment n'est détruit qu'après que le dernier processus l'a détaché.
IPC_INFO - Renvoie les informations sur les limites et les paramètres de la mémoire partagée dans la structure pointée par buf.
SHM_INFO - Renvoie une structure shm_info contenant des informations sur les ressources système consommées par la mémoire partagée.
Le troisième argument, buf, est un pointeur vers la structure de mémoire partagée nommée struct shmid_ds. Les valeurs de cette structure seraient utilisées pour définir ou obtenir selon cmd.
Cet appel renvoie la valeur en fonction de la commande passée. En cas de succès de IPC_INFO et SHM_INFO ou SHM_STAT renvoie l'index ou l'identifiant du segment de mémoire partagée ou 0 pour les autres opérations et -1 en cas d'échec. Pour connaître la cause de l'échec, vérifiez avec la variable errno ou la fonction perror ().
Prenons l'exemple de programme suivant.
Créez deux processus, un pour écrire dans la mémoire partagée (shm_write.c) et un autre pour lire depuis la mémoire partagée (shm_read.c)
Le programme effectue l'écriture dans la mémoire partagée par le processus d'écriture (shm_write.c) et la lecture de la mémoire partagée par le processus de lecture (shm_read.c)
Dans la mémoire partagée, le processus d'écriture crée une mémoire partagée de taille 1K (et des indicateurs) et attache la mémoire partagée
Le processus d'écriture écrit 5 fois les Alphabets de «A» à «E» chacun de 1023 octets dans la mémoire partagée. Le dernier octet signifie la fin du tampon
Le processus de lecture lit à partir de la mémoire partagée et écrit dans la sortie standard
Les actions de lecture et d'écriture sont effectuées simultanément
Une fois l'écriture terminée, le processus d'écriture se met à jour pour indiquer la fin de l'écriture dans la mémoire partagée (avec la variable complete dans struct shmseg)
Le processus de lecture effectue la lecture à partir de la mémoire partagée et s'affiche sur la sortie jusqu'à ce qu'il obtienne une indication de la fin du processus d'écriture (variable complète dans struct shmseg)
Effectue un processus de lecture et d'écriture plusieurs fois pour simplifier et aussi pour éviter les boucles infinies et compliquer le programme
Voici le code pour le processus d'écriture (Écriture dans la mémoire partagée - Fichier: shm_write.c)
/* Filename: shm_write.c */
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<string.h>
#include<errno.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#define BUF_SIZE 1024
#define SHM_KEY 0x1234
struct shmseg {
int cnt;
int complete;
char buf[BUF_SIZE];
};
int fill_buffer(char * bufptr, int size);
int main(int argc, char *argv[]) {
int shmid, numtimes;
struct shmseg *shmp;
char *bufptr;
int spaceavailable;
shmid = shmget(SHM_KEY, sizeof(struct shmseg), 0644|IPC_CREAT);
if (shmid == -1) {
perror("Shared memory");
return 1;
}
// Attach to the segment to get a pointer to it.
shmp = shmat(shmid, NULL, 0);
if (shmp == (void *) -1) {
perror("Shared memory attach");
return 1;
}
/* Transfer blocks of data from buffer to shared memory */
bufptr = shmp->buf;
spaceavailable = BUF_SIZE;
for (numtimes = 0; numtimes < 5; numtimes++) {
shmp->cnt = fill_buffer(bufptr, spaceavailable);
shmp->complete = 0;
printf("Writing Process: Shared Memory Write: Wrote %d bytes\n", shmp->cnt);
bufptr = shmp->buf;
spaceavailable = BUF_SIZE;
sleep(3);
}
printf("Writing Process: Wrote %d times\n", numtimes);
shmp->complete = 1;
if (shmdt(shmp) == -1) {
perror("shmdt");
return 1;
}
if (shmctl(shmid, IPC_RMID, 0) == -1) {
perror("shmctl");
return 1;
}
printf("Writing Process: Complete\n");
return 0;
}
int fill_buffer(char * bufptr, int size) {
static char ch = 'A';
int filled_count;
//printf("size is %d\n", size);
memset(bufptr, ch, size - 1);
bufptr[size-1] = '\0';
if (ch > 122)
ch = 65;
if ( (ch >= 65) && (ch <= 122) ) {
if ( (ch >= 91) && (ch <= 96) ) {
ch = 65;
}
}
filled_count = strlen(bufptr);
//printf("buffer count is: %d\n", filled_count);
//printf("buffer filled is:%s\n", bufptr);
ch++;
return filled_count;
}
Étapes de compilation et d'exécution
Writing Process: Shared Memory Write: Wrote 1023 bytes
Writing Process: Shared Memory Write: Wrote 1023 bytes
Writing Process: Shared Memory Write: Wrote 1023 bytes
Writing Process: Shared Memory Write: Wrote 1023 bytes
Writing Process: Shared Memory Write: Wrote 1023 bytes
Writing Process: Wrote 5 times
Writing Process: Complete
Voici le code pour le processus de lecture (lecture à partir de la mémoire partagée et écriture sur la sortie standard - Fichier: shm_read.c)
/* Filename: shm_read.c */
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<string.h>
#include<errno.h>
#include<stdlib.h>
#define BUF_SIZE 1024
#define SHM_KEY 0x1234
struct shmseg {
int cnt;
int complete;
char buf[BUF_SIZE];
};
int main(int argc, char *argv[]) {
int shmid;
struct shmseg *shmp;
shmid = shmget(SHM_KEY, sizeof(struct shmseg), 0644|IPC_CREAT);
if (shmid == -1) {
perror("Shared memory");
return 1;
}
// Attach to the segment to get a pointer to it.
shmp = shmat(shmid, NULL, 0);
if (shmp == (void *) -1) {
perror("Shared memory attach");
return 1;
}
/* Transfer blocks of data from shared memory to stdout*/
while (shmp->complete != 1) {
printf("segment contains : \n\"%s\"\n", shmp->buf);
if (shmp->cnt == -1) {
perror("read");
return 1;
}
printf("Reading Process: Shared Memory: Read %d bytes\n", shmp->cnt);
sleep(3);
}
printf("Reading Process: Reading Done, Detaching Shared Memory\n");
if (shmdt(shmp) == -1) {
perror("shmdt");
return 1;
}
printf("Reading Process: Complete\n");
return 0;
}
Étapes de compilation et d'exécution
segment contains :
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
Reading Process: Shared Memory: Read 1023 bytes
segment contains :
"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
Reading Process: Shared Memory: Read 1023 bytes
segment contains :
"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
Reading Process: Shared Memory: Read 1023 bytes
segment contains :
"DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
Reading Process: Shared Memory: Read 1023 bytes
segment contains :
"EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
Reading Process: Shared Memory: Read 1023 bytes
Reading Process: Reading Done, Detaching Shared Memory
Reading Process: Complete