共有メモリ

共有メモリは、2つ以上のプロセス間で共有されるメモリです。しかし、なぜメモリやその他の通信手段を共有する必要があるのでしょうか。

繰り返しになりますが、各プロセスには独自のアドレススペースがあり、プロセスが独自のアドレススペースから他のプロセスに情報を通信する場合は、IPC(プロセス間通信)技術でのみ可能です。すでに認識しているように、コミュニケーションは関連するプロセス間または関連しないプロセス間で行うことができます。

通常、相互に関連するプロセス通信は、パイプまたは名前付きパイプを使用して実行されます。無関係なプロセス(たとえば、ある端末で実行されている1つのプロセスと、別の端末で実行されている別のプロセス)の通信は、名前付きパイプを使用するか、共有メモリとメッセージキューの一般的なIPC技術を介して実行できます。

パイプと名前付きパイプのIPC手法を見てきましたが、残りのIPC手法、つまり共有メモリ、メッセージキュー、セマフォ、信号、メモリマッピングについて知るときが来ました。

この章では、共有メモリについてすべて説明します。

2つ以上のプロセス間で通信するために共有メモリを使用することはわかっていますが、共有メモリを使用する前に、システムコールで何を行う必要があるかを見てみましょう。

  • 共有メモリセグメントを作成するか、作成済みの共有メモリセグメントを使用します(shmget())

  • 作成済みの共有メモリセグメントにプロセスをアタッチします(shmat())

  • すでに接続されている共有メモリセグメントからプロセスを切り離します(shmdt())

  • 共有メモリセグメントの制御操作(shmctl())

共有メモリに関連するシステムコールの詳細をいくつか見てみましょう。

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

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

上記のシステムコールは、SystemV共有メモリセグメントを作成または割り当てます。渡す必要のある引数は次のとおりです-

ザ・ first argument, key,共有メモリセグメントを認識します。キーは、任意の値、またはライブラリ関数ftok()から派生できる値のいずれかです。キーはIPC_PRIVATEにすることもできます。つまり、サーバーとクライアント(親と子の関係)としてプロセスを実行します。つまり、相互に関連するプロセス通信です。クライアントがこのキーで共有メモリを使用する場合は、サーバーの子プロセスである必要があります。また、親が共有メモリを取得した後、子プロセスを作成する必要があります。

ザ・ second argument, size, は、PAGE_SIZEの倍数に丸められた共有メモリセグメントのサイズです。

ザ・ third argument, shmflg,IPC_CREAT(新しいセグメントを作成する)やIPC_EXCL(IPC_CREATとともに使用して新しいセグメントを作成し、セグメントがすでに存在する場合は呼び出しが失敗する)などの必要な共有メモリフラグを指定します。権限も渡す必要があります。

Note −権限の詳細については、前のセクションを参照してください。

この呼び出しは、成功した場合は有効な共有メモリ識別子(共有メモリの以降の呼び出しに使用)を返し、失敗した場合は-1を返します。失敗の原因を知るには、errno変数またはperror()関数で確認してください。

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

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

上記のシステムコールは、System V共有メモリセグメントの共有メモリ操作を実行します。つまり、共有メモリセグメントを呼び出しプロセスのアドレス空間に接続します。渡す必要のある引数は次のとおりです-

The first argument, shmid,共有メモリセグメントの識別子です。このIDは、shmget()システムコールの戻り値である共有メモリ識別子です。

The second argument, shmaddr,添付アドレスを指定することです。shmaddrがNULLの場合、システムはデフォルトでセグメントを接続するための適切なアドレスを選択します。shmaddrがNULLでなく、SHM_RNDがshmflgで指定されている場合、アタッチはSHMLBAの最も近い倍数(下限アドレス)のアドレスに等しくなります。それ以外の場合、shmaddrは、共有メモリ接続が発生/開始するページ整列アドレスである必要があります。

The third argument, shmflg, SHM_RND(アドレスをSHMLBAに丸める)、SHM_EXEC(セグメントの内容を実行できるようにする)、SHM_RDONLY(読み取り専用の目的でセグメントをアタッチします。デフォルトでは読み取り/書き込み)など、必要な共有メモリフラグを指定します。またはSHM_REMAP(shmaddrで指定された範囲内の既存のマッピングを置き換え、セグメントの終わりまで継続します)。

この呼び出しは、成功した場合は接続された共有メモリセグメントのアドレスを返し、失敗した場合は-1を返します。失敗の原因を知るには、errno変数またはperror()関数で確認してください。

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

int shmdt(const void *shmaddr)

上記のシステムコールは、呼び出しプロセスのアドレス空間から共有メモリセグメントをデタッチするSystemV共有メモリセグメントの共有メモリ操作を実行します。渡す必要のある引数は-です。

引数shmaddrは、デタッチされる共有メモリセグメントのアドレスです。デタッチされるセグメントは、shmat()システムコールによって返されるアドレスである必要があります。

この呼び出しは、成功した場合は0を返し、失敗した場合は-1を返します。失敗の原因を知るには、errno変数またはperror()関数で確認してください。

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

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

上記のシステムコールは、SystemV共有メモリセグメントの制御操作を実行します。次の引数を渡す必要があります-

最初の引数shmidは、共有メモリセグメントの識別子です。このIDは、shmget()システムコールの戻り値である共有メモリ識別子です。

2番目の引数cmdは、共有メモリセグメントで必要な制御操作を実行するためのコマンドです。

cmdの有効な値は次のとおりです。

  • IPC_STAT− struct shmid_dsの各メンバーの現在の値の情報を、bufが指す渡された構造体にコピーします。このコマンドには、共有メモリセグメントへの読み取り権限が必要です。

  • IPC_SET −構造体bufが指すユーザーID、所有者のグループID、権限などを設定します。

  • IPC_RMID−破棄するセグメントをマークします。セグメントは、最後のプロセスで切り離された後でのみ破棄されます。

  • IPC_INFO −bufが指す構造体の共有メモリ制限とパラメータに関する情報を返します。

  • SHM_INFO −共有メモリによって消費されたシステムリソースに関する情報を含むshm_info構造体を返します。

3番目の引数bufは、structshmid_dsという名前の共有メモリ構造体へのポインタです。この構造体の値は、cmdに従ってsetまたはgetのいずれかに使用されます。

この呼び出しは、渡されたコマンドに応じて値を返します。IPC_INFOが成功すると、SHM_INFOまたはSHM_STATは、共有メモリセグメントのインデックスまたは識別子を返します。他の操作の場合は0を返し、失敗した場合は-1を返します。失敗の原因を知るには、errno変数またはperror()関数で確認してください。

次のサンプルプログラムを考えてみましょう。

  • 2つのプロセスを作成します。1つは共有メモリへの書き込み用(shm_write.c)で、もう1つは共有メモリからの読み取り用(shm_read.c)です。

  • プログラムは、書き込みプロセス(shm_write.c)による共有メモリへの書き込みと、読み取りプロセス(shm_read.c)による共有メモリからの読み取りを実行します。

  • 共有メモリでは、書き込みプロセスにより、サイズ1K(およびフラグ)の共有メモリが作成され、共有メモリが接続されます。

  • 書き込みプロセスは、それぞれ1023バイトの「A」から「E」までのアルファベットの5倍を共有メモリに書き込みます。最後のバイトはバッファの終わりを示します

  • 読み取りプロセスは、共有メモリから読み取り、標準出力に書き込みます

  • 読み取りと書き込みのプロセスアクションは同時に実行されます

  • 書き込みが完了すると、書き込みプロセスが更新され、共有メモリへの書き込みが完了したことが示されます(struct shmsegに完全な変数があります)。

  • 読み取りプロセスは、共有メモリからの読み取りを実行し、書き込みプロセスの完了が示されるまで出力に表示します(struct shmsegの完全な変数)。

  • 単純化のために、また無限ループやプログラムの複雑化を回避するために、読み取りと書き込みのプロセスを数回実行します

以下は、書き込みプロセスのコードです(共有メモリへの書き込み–ファイル: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;
}

コンパイルと実行のステップ

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

以下は、読み取りプロセスのコードです(共有メモリからの読み取りと標準出力への書き込み–ファイル: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;
}

コンパイルと実行のステップ

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