Memoria compartilhada

A memória compartilhada é uma memória compartilhada entre dois ou mais processos. No entanto, por que precisamos compartilhar memória ou algum outro meio de comunicação?

Para reiterar, cada processo tem seu próprio espaço de endereço, se algum processo deseja se comunicar com alguma informação de seu próprio espaço de endereço para outros processos, então isso só é possível com técnicas de IPC (comunicação entre processos). Como já sabemos, a comunicação pode ser entre processos relacionados ou não.

Normalmente, a comunicação de processos inter-relacionados é realizada usando Pipes ou Pipes Nomeados. A comunicação de processos não relacionados (digamos, um processo em execução em um terminal e outro processo em outro terminal) pode ser realizada usando Pipes Nomeados ou por meio de técnicas IPC populares de Memória Compartilhada e Filas de Mensagens.

Vimos as técnicas de IPC de Pipes e Pipes Nomeados e agora é hora de conhecer as técnicas de IPC restantes, a saber, Memória Compartilhada, Filas de Mensagens, Semáforos, Sinais e Mapeamento de Memória.

Neste capítulo, saberemos tudo sobre memória compartilhada.

Sabemos que para nos comunicarmos entre dois ou mais processos, usamos memória compartilhada, mas antes de usar a memória compartilhada o que precisa ser feito com as chamadas de sistema, vamos ver isso -

  • Crie o segmento de memória compartilhada ou use um segmento de memória compartilhada já criado (shmget ())

  • Anexe o processo ao segmento de memória compartilhada já criado (shmat ())

  • Desanexar o processo do segmento de memória compartilhada já anexado (shmdt ())

  • Operações de controle no segmento de memória compartilhada (shmctl ())

Vejamos alguns detalhes das chamadas do sistema relacionadas à memória compartilhada.

#include <sys/ipc.h>
#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg)

A chamada do sistema acima cria ou aloca um segmento de memória compartilhada do System V. Os argumentos que precisam ser passados ​​são os seguintes -

o first argument, key,reconhece o segmento de memória compartilhada. A chave pode ser um valor arbitrário ou derivado da função de biblioteca ftok (). A chave também pode ser IPC_PRIVATE, significa executar processos como servidor e cliente (relacionamento pai e filho), ou seja, comunicação de processos inter-relacionados. Se o cliente deseja usar memória compartilhada com esta chave, então ela deve ser um processo filho do servidor. Além disso, o processo filho precisa ser criado depois que o pai obteve uma memória compartilhada.

o second argument, size, é o tamanho do segmento de memória compartilhada arredondado para múltiplos de PAGE_SIZE.

o third argument, shmflg,especifica os sinalizadores de memória compartilhada necessários, como IPC_CREAT (criando novo segmento) ou IPC_EXCL (usado com IPC_CREAT para criar novo segmento e a chamada falha, se o segmento já existir). Precisa passar as permissões também.

Note - Consulte as seções anteriores para obter detalhes sobre as permissões.

Esta chamada retornaria um identificador de memória compartilhada válido (usado para chamadas adicionais de memória compartilhada) em caso de sucesso e -1 em caso de falha. Para saber a causa da falha, verifique com a variável errno ou função perror ().

#include <sys/types.h>
#include <sys/shm.h>

void * shmat(int shmid, const void *shmaddr, int shmflg)

A chamada do sistema acima executa a operação de memória compartilhada para o segmento de memória compartilhada do System V, ou seja, anexando um segmento de memória compartilhada ao espaço de endereço do processo de chamada. Os argumentos que precisam ser passados ​​são os seguintes -

The first argument, shmid,é o identificador do segmento de memória compartilhada. Este id é o identificador de memória compartilhada, que é o valor de retorno da chamada de sistema shmget ().

The second argument, shmaddr,é especificar o endereço do anexo. Se shmaddr é NULL, o sistema, por padrão, escolhe o endereço adequado para anexar o segmento. Se shmaddr não for NULL e SHM_RND for especificado em shmflg, o attach é igual ao endereço do múltiplo mais próximo de SHMLBA (Lower Boundary Address). Caso contrário, shmaddr deve ser um endereço alinhado por página no qual o anexo de memória compartilhada ocorre / inicia.

The third argument, shmflg, especifica os sinalizadores de memória compartilhada necessários, como SHM_RND (arredondando o endereço para SHMLBA) ou SHM_EXEC (permite que o conteúdo do segmento seja executado) ou SHM_RDONLY (anexa o segmento para fins somente leitura, por padrão é leitura-gravação) ou SHM_REMAP (substitui o mapeamento existente no intervalo especificado por shmaddr e continuando até o final do segmento).

Esta chamada retornaria o endereço do segmento de memória compartilhada anexado em caso de sucesso e -1 em caso de falha. Para saber a causa da falha, verifique com a variável errno ou função perror ().

#include <sys/types.h>
#include <sys/shm.h>

int shmdt(const void *shmaddr)

A chamada do sistema acima executa a operação de memória compartilhada para o segmento de memória compartilhada do Sistema V de desanexar o segmento de memória compartilhada do espaço de endereço do processo de chamada. O argumento que precisa ser passado é -

O argumento, shmaddr, é o endereço do segmento de memória compartilhada a ser desanexado. O segmento a ser desanexado deve ser o endereço retornado pela chamada de sistema shmat ().

Esta chamada retornaria 0 em caso de sucesso e -1 em caso de falha. Para saber a causa da falha, verifique com a variável errno ou função perror ().

#include <sys/ipc.h>
#include <sys/shm.h>

int shmctl(int shmid, int cmd, struct shmid_ds *buf)

A chamada do sistema acima executa a operação de controle para um segmento de memória compartilhada do System V. Os seguintes argumentos precisam ser passados ​​-

O primeiro argumento, shmid, é o identificador do segmento de memória compartilhada. Este id é o identificador de memória compartilhada, que é o valor de retorno da chamada de sistema shmget ().

O segundo argumento, cmd, é o comando para executar a operação de controle necessária no segmento de memória compartilhada.

Os valores válidos para cmd são -

  • IPC_STAT- Copia as informações dos valores atuais de cada membro de struct shmid_ds para a estrutura passada apontada por buf. Este comando requer permissão de leitura para o segmento de memória compartilhada.

  • IPC_SET - Define o ID do usuário, ID do grupo do proprietário, permissões, etc. apontados pela estrutura buf.

  • IPC_RMID- Marca o segmento a ser destruído. O segmento é destruído somente depois que o último processo o separa.

  • IPC_INFO - Retorna a informação sobre os limites e parâmetros da memória compartilhada na estrutura apontada por buf.

  • SHM_INFO - Retorna uma estrutura shm_info contendo informações sobre os recursos do sistema consumidos pela memória compartilhada.

O terceiro argumento, buf, é um ponteiro para a estrutura de memória compartilhada chamada struct shmid_ds. Os valores dessa estrutura seriam usados ​​para definir ou obter como por cmd.

Esta chamada retorna o valor dependendo do comando passado. Após o sucesso de IPC_INFO e SHM_INFO ou SHM_STAT retorna o índice ou identificador do segmento de memória compartilhada ou 0 para outras operações e -1 em caso de falha. Para saber a causa da falha, verifique com a variável errno ou função perror ().

Vamos considerar o seguinte programa de exemplo.

  • Crie dois processos, um é para escrever na memória compartilhada (shm_write.c) e outro é para ler na memória compartilhada (shm_read.c)

  • O programa executa a gravação na memória compartilhada pelo processo de gravação (shm_write.c) e a leitura da memória compartilhada pelo processo de leitura (shm_read.c)

  • Na memória compartilhada, o processo de escrita, cria uma memória compartilhada de tamanho 1K (e sinalizadores) e anexa a memória compartilhada

  • O processo de gravação grava 5 vezes os alfabetos de 'A' a 'E' cada um de 1023 bytes na memória compartilhada. Último byte significa o fim do buffer

  • O processo de leitura leria da memória compartilhada e gravaria na saída padrão

  • As ações do processo de leitura e escrita são realizadas simultaneamente

  • Após a conclusão da gravação, o processo de gravação é atualizado para indicar a conclusão da gravação na memória compartilhada (com a variável completa em struct shmseg)

  • O processo de leitura realiza a leitura da memória compartilhada e exibe na saída até obter a indicação da conclusão do processo de gravação (variável completa em struct shmseg)

  • Executa o processo de leitura e escrita algumas vezes para simplificar e também para evitar loops infinitos e complicar o programa

A seguir está o código para o processo de gravação (Gravando na Memória Compartilhada - Arquivo: 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;
}

Etapas de compilação e execução

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

A seguir está o código para o processo de leitura (leitura da memória compartilhada e gravação na saída padrão - Arquivo: 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;
}

Etapas de compilação e execução

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