今回は、前回作ったプログラムを少し改変して、書き込み側と読み出し側を別々のプログラムにしてみます。
注意する点は、書き込み側でハンドルを閉じてしまったり、プログラムそのものが終了してしまうと、当たり前ですが読み出し側ではもう読み出すことができません。また、今回はメモリマップトファイルを複数用意しておきます。
では、書き込み側のプログラムを見てみましょう。
/* memmapx.c */ /*書き込み専用*/
#include <stdio.h>
#include <windows.h>
#include <conio.h>
int main()
{
LPSTR lpStr;
HANDLE hFM[4];
char szName[][16] = {"CAT0", "CAT1", "CAT2", "CAT3"}, szNo[8],
szBuf[1024];
int i, nameNo;
for (i = 0; i < 4; i++)
hFM[i] = NULL;
while (1) {
printf("何番の書き込みをしますか(0-3, 9:終了)---");
gets(szNo);
nameNo = atoi(szNo);
if (nameNo == 9)
break;
if (nameNo < 0 || nameNo > 3) {
printf("不正な番号です\n\n");
continue;
}
hFM[nameNo] = CreateFileMapping(
(HANDLE)-1,
NULL,
PAGE_READWRITE,
0,
1024,
szName[nameNo]);
if (hFM[nameNo] == NULL) {
printf("CreateFileMapping 失敗\n");
return -1;
}
if (GetLastError() == ERROR_ALREADY_EXISTS) {
printf("すでにマッピングオブジェクトが存在しますので、書きかえます\n");
}
lpStr = (LPSTR)MapViewOfFile(hFM[nameNo],
FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (lpStr == NULL) {
printf("MapViewOfFile失敗\n");
CloseHandle(hFM);
return -2;
}
printf("書き込み文章---");
gets(szBuf);
strcpy(lpStr, szBuf);
strcat(lpStr, "\n");
UnmapViewOfFile(lpStr);
printf("書き込み完了です\n");
}
printf("何かキーを打つと終了します\n");
_getch();
for (i = 0; i < 4; i++) {
if (hFM[i] != NULL)
CloseHandle(hFM[i]);
}
return 0;
}
ハンドルを配列にしておきます。そして、最初にハンドルにNULLを割り当てておきます。
すると、ハンドルがNULLかどうかで、最後にハンドルをクローズすべきかどうかを判定できます。無限ループを作っておいて、このなかでマッピングオブジェクトを作成します。
最初にユーザーに、0-3までの番号を選択してもらいます。
これで、オブジェクト名を決めてもらうわけです。("CAT0"から"CAT3"まで) そして、その番号(名前)のファイルマッピングオブジェクトを作成します。
すでに使用済みの番号を選択すると、GetLastError関数はERROR_ALREADY_EXISTSを 返しますので、内容の書き換えをすることになります。
ファイルマップトオブジェクトのハンドルを取得できたら、自分のプロセスで使用できるようにMapViewOfFile関数で、マッピングを行います。
そして、書き込みを行います。
書き込みが終わったらUnmapViewOfFile関数で、アンマップしておきます。 これを、繰り返します。ユーザーが9を選択したら、ループを抜けますが、プログラムは_getch関数で入力待ちの状態となります。
そして、この間に読み出し側で読み出すのを待つわけです。
本当に終了したいときは、なにかのキーを押します。
すると、作成されたメモリマップトオブジェクトのハンドルだけをクローズしてプログラムは終了します。
次に、読み出し側のプログラムを見てみましょう。
/* memmapxr */ /*読み取り専用*/
#include <stdio.h>
#include <windows.h>
int main()
{
LPSTR lpStr;
HANDLE hFM;
char szName[][16] = {"CAT0", "CAT1", "CAT2", "CAT3"}, szNo[8],
szBuf[1024];
int nameNo;
while (1) {
printf("何番の読み取りをしますか(0-3, 9:終了)---");
gets(szNo);
nameNo = atoi(szNo);
if (nameNo == 9)
break;
if (nameNo < 0 || nameNo > 3) {
printf("不正な番号です。\n\n");
continue;
}
hFM = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, szName[nameNo]);
if (!hFM) {
printf("ファイルマッピングのオープン失敗\n");
continue;
}
lpStr = (LPSTR)MapViewOfFile(hFM,
FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (lpStr == NULL) {
CloseHandle(hFM);
printf( "MapViewOfFilw 失敗\n");
return -1;
}
lpStr = MapViewOfFile(hFM, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (lpStr == NULL) {
printf("MapViewOfFile 失敗\n");
CloseHandle(hFM);
return -2;
}
strcpy(szBuf, lpStr);
strcat(szBuf, "\n");
printf("書き込み内容--%s", szBuf);
if(UnmapViewOfFile(lpStr) == 0) {
printf("UnmapViewOfFile 失敗\n");
CloseHandle(hFM);
return -3;
}
CloseHandle(hFM);
}
return 0;
}
最初に、ユーザーに読み出したいメモリマップトオブジェクトの番号を選択させます。オブジェクト名が決まったら、OpenFileMapping関数で、オープンします。
MapViewOfFile関数で、マッピングをして自分のプロセスで読めるようにします。
読み出したら、UnmapViewOfFile関数で、アンマップします。
さらに、ハンドルをクローズします。
これを繰り返します。書き込み側と違うのは、読み出したらハンドルまでクローズしてしまう点です。
このプログラムを起動して、実際の動作を確認してみてください。
Update Jul/11/2005 By Y.Kumei