ファイルの途中からメモリマップドファイルのマッピングをする

mnr2008-09-16


ファイルの途中からマッピングを開始しようと思ったのだが、なかなかうまくいかず、単なるNULLポインタしか取得できなかった。ようやく理由が分かった。オフセットがシステム指定の数の倍数で、自由ではないらしい。とりあえず、ファイルの途中からマッピングをさせることができた。このソースコードを実行して、ファイルを生成させるとちゃんと途中からマッピングした結果を見ることができる。

john.c

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
	int i = 0;
	int tmp = 0;
	int memblock = 0;
	int size = 65536;
	char* mydata = NULL;
	HANDLE h = 0;
	HANDLE h2 = 0;
	DWORD errorcheck = 0;
	SYSTEM_INFO  SystemInfo;

	// [01]システム情報を得る
	GetSystemInfo(&SystemInfo);

	// [02]メモリマップのオフセット最小単位をとってくる
	memblock = SystemInfo.dwAllocationGranularity; 

	// [03] メモリをマッピングをするファイルを作成する
	h = CreateFile(
		"john_3_16.dat" ,
		GENERIC_READ | GENERIC_WRITE ,
		FILE_SHARE_READ | FILE_SHARE_WRITE ,
		NULL ,
		CREATE_ALWAYS ,
		FILE_ATTRIBUTE_NORMAL ,
		NULL
		);
	errorcheck = GetLastError();
	if (h == INVALID_HANDLE_VALUE) {
		printf("エラー(%d)\n", errorcheck);
	}

	// [04] ファイルのマッピングを作成する
	h2 = CreateFileMapping(h, NULL, PAGE_READWRITE, 0, memblock*3, "mmap");
	errorcheck = GetLastError();
	if (h2 == INVALID_HANDLE_VALUE) {
		printf("エラー(%d)\n", errorcheck);
	}

	// [05] ファイルビューをマッピングする
	mydata = MapViewOfFile(h2, FILE_MAP_ALL_ACCESS, 0, memblock, memblock*2);
	errorcheck = GetLastError();
	if (mydata == NULL) {
		printf("エラー(%d)\n", errorcheck);
	}

	// [06]確保したヒープを自由に使ってみる
	printf("address: 0x%p\n", mydata);
	for (i = 0; i < size; i++) {
		mydata[i] = ' ';
	}
	strcpy(mydata, "For God so loved the world that He gave His only begotten Son, ");
	strcat(mydata, "that whoever believes in Him should not perish");
	strcat(mydata, " but have everlasting life.");

	// [07] ファイルのビューをフラッシュする
	tmp = FlushViewOfFile(mydata, 0);
	errorcheck = GetLastError();
	if (tmp == 0) {
		printf("エラー(%d)\n", errorcheck);
	}

	// [08] ファイルビューをマッピング解除する
	tmp = UnmapViewOfFile(mydata);
	errorcheck = GetLastError();
	if (tmp == 0) {
		printf("エラー(%d)\n", errorcheck);
	}
	CloseHandle(h2);
	CloseHandle(h);

	return 0;
}