首页
社区
课程
招聘
[原创]Windows系统程序设计之内存映射
发表于: 2006-8-11 22:03 16897

[原创]Windows系统程序设计之内存映射

2006-8-11 22:03
16897
typedef struct _FILE_ITEM_INFO {
	DWORD	dwLowFileSize ;		// 文件大小低字段
	DWORD	dwHighFileSize ;	// 文件大小高字段
	DWORD	dwPartSize ;			// 文件块大小
	DWORD	dwPartNum ;		// 文件块数量
	CString	szFileName ;			// 源文件名
} FILE_ITEM_INFO ;
typedef FILE_ITEM_INFO* PFILE_ITEM_INFO ;
DWORD CFD::FDFileDivide	( PFILE_ITEM_INFO pItem )
{
	// 删除该文件原有的分块文件
	this->DeleteAllPartFiles ( pItem->szFileName ) ;

	// 创建信息文件
	HANDLE hFile = CreateFile ( 
		pItem->szFileName + ".INFO",  
		GENERIC_READ|GENERIC_WRITE, 
		FILE_SHARE_READ|FILE_SHARE_WRITE, 
		NULL, 
		CREATE_ALWAYS, 
		FILE_ATTRIBUTE_NORMAL, 
		NULL ) ;
	if ( hFile == INVALID_HANDLE_VALUE )
		return GetLastError() ;
	
	// 写入信息文件
	DWORD dwWriteByte ;
	WriteFile ( hFile, &(pItem->dwLowFileSize),	sizeof(DWORD),	&dwWriteByte, NULL ) ;
	WriteFile ( hFile, &(pItem->dwPartSize),	sizeof(DWORD),	&dwWriteByte, NULL ) ;
	WriteFile ( hFile, &(pItem->dwPartNum),		sizeof(DWORD),	&dwWriteByte, NULL ) ;
	CloseHandle ( hFile ) ;

	// 打开目标文件
	hFile = CreateFile ( 
		pItem->szFileName,  
		GENERIC_READ, 
		FILE_SHARE_READ|FILE_SHARE_WRITE, 
		NULL, 
		OPEN_EXISTING, 
		FILE_ATTRIBUTE_NORMAL, 
		NULL ) ;
	if ( hFile == INVALID_HANDLE_VALUE )
		return GetLastError() ;

	// 创建文件内存映射内核对象
	HANDLE hMapFile = CreateFileMapping ( 
		hFile, 	
		NULL, 
		PAGE_READONLY, 
		0, 
		0, 
		NULL ) ;
	if ( hMapFile == NULL )
	{
		CloseHandle ( hFile ) ;
		return GetLastError() ;
	}


	CString TempStr ;
	DWORD	dwCurAddr = 0, dwCurPart = 0 ;
	LPVOID lpMapAddr = 0 ;

	// 分块循环映射文件
	for ( UINT i = 1; i <= pItem->dwPartNum; i++ )
	{
		dwCurPart = pItem->dwLowFileSize - dwCurAddr ;
		if ( dwCurPart > pItem->dwPartSize )
			dwCurPart = pItem->dwPartSize ;

		lpMapAddr = MapViewOfFile ( hMapFile, FILE_MAP_READ, 0, dwCurAddr, dwCurPart ) ;
		if ( lpMapAddr == NULL )
		{
			CloseHandle ( hMapFile ) ;
			CloseHandle ( hFile ) ;
			return GetLastError() ;
		}

		dwCurAddr += dwCurPart ;

		TempStr.Format ( "%s.PART_%d", pItem->szFileName, i ) ;
		DeleteFile ( TempStr ) ;
		
		HANDLE hNewFile = CreateFile ( 
			TempStr,
			GENERIC_READ|GENERIC_WRITE, 
			FILE_SHARE_READ|FILE_SHARE_WRITE, 
			NULL, 
			CREATE_ALWAYS, 
			FILE_ATTRIBUTE_NORMAL, 
			NULL ) ;
		if ( hFile == INVALID_HANDLE_VALUE )
			return GetLastError() ;
		
		HANDLE hNewMapFile = CreateFileMapping (
			hNewFile, 	
			NULL, 
			PAGE_READWRITE, 
			0, 
			dwCurPart, 
			NULL ) ;
		if ( hNewMapFile == NULL )
		{
			CloseHandle ( hNewFile ) ;
			return GetLastError() ;
		}

		LPVOID lpNewMapAddr = MapViewOfFile ( hNewMapFile, FILE_MAP_WRITE, 0, 0, 0 ) ;
		if ( lpMapAddr == NULL )
		{
			CloseHandle ( hNewMapFile ) ;
			CloseHandle ( hNewFile ) ;
			return GetLastError() ;
		}

		memcpy ( lpNewMapAddr, lpMapAddr, dwCurPart ) ;
		
		UnmapViewOfFile ( lpMapAddr ) ;
		UnmapViewOfFile ( lpNewMapAddr ) ;
		CloseHandle ( hNewMapFile ) ;
		CloseHandle ( hNewFile ) ;
	}

	CloseHandle ( hMapFile ) ;
	CloseHandle ( hFile ) ;
	return 0 ;
}
DWORD CFD::FDFileConnect	( PFILE_ITEM_INFO pItem )
{
	DeleteFile ( pItem->szFileName ) ;

	// 打开目标文件
	HANDLE hFile = CreateFile ( 
		pItem->szFileName,  
		GENERIC_READ|GENERIC_WRITE, 
		FILE_SHARE_READ|FILE_SHARE_WRITE, 
		NULL, 
		CREATE_ALWAYS, 
		FILE_ATTRIBUTE_NORMAL, 
		NULL ) ;
	if ( hFile == INVALID_HANDLE_VALUE )
		return GetLastError() ;

	// 创建文件内存映射内核对象
	HANDLE hMapFile = CreateFileMapping ( 
		hFile, 	
		NULL, 
		PAGE_READWRITE, 
		0, 
		pItem->dwLowFileSize, 
		NULL ) ;
	if ( hMapFile == NULL )
	{
		CloseHandle ( hFile ) ;
		return GetLastError() ;
	}

	CString TempStr ;
	DWORD	dwCurAddr = 0, dwCurPart = 0 ;
	LPVOID lpMapAddr = 0 ;

	// 分块循环映射文件
	for ( UINT i = 1; i <= pItem->dwPartNum; i++ )
	{
		dwCurPart = pItem->dwLowFileSize - dwCurAddr ;
		if ( dwCurPart > pItem->dwPartSize )
			dwCurPart = pItem->dwPartSize ;

		lpMapAddr = MapViewOfFile ( hMapFile, FILE_MAP_WRITE, 0, dwCurAddr, dwCurPart ) ;
		if ( lpMapAddr == NULL )
		{
			CloseHandle ( hMapFile ) ;
			CloseHandle ( hFile ) ;
			return GetLastError() ;
		}

		dwCurAddr += dwCurPart ;

		TempStr.Format ( "%s.PART_%d", pItem->szFileName, i ) ;
		
		HANDLE hNewFile = CreateFile ( 
			TempStr,
			GENERIC_READ, 
			FILE_SHARE_READ|FILE_SHARE_WRITE, 
			NULL, 
			OPEN_EXISTING, 
			FILE_ATTRIBUTE_NORMAL, 
			NULL ) ;
		if ( hFile == INVALID_HANDLE_VALUE )
		{
			UnmapViewOfFile ( lpMapAddr ) ;
			CloseHandle ( hMapFile ) ;
			CloseHandle ( hFile ) ;
			return GetLastError() ;
		}
		
		HANDLE hNewMapFile = CreateFileMapping (
			hNewFile, 	
			NULL, 
			PAGE_READONLY, 
			0, 
			0, 
			NULL ) ;
		if ( hNewMapFile == NULL )
		{	
			UnmapViewOfFile ( lpMapAddr ) ;
			CloseHandle ( hMapFile ) ;
			CloseHandle ( hFile ) ;
			CloseHandle ( hNewFile ) ;
			return GetLastError() ;
		}

		LPVOID lpNewMapAddr = MapViewOfFile ( hNewMapFile, FILE_MAP_READ, 0, 0, 0 ) ;
		if ( lpMapAddr == NULL )
		{	
			UnmapViewOfFile ( lpMapAddr ) ;
			CloseHandle ( hMapFile ) ;
			CloseHandle ( hFile ) ;
			CloseHandle ( hNewMapFile ) ;
			CloseHandle ( hNewFile ) ;
			return GetLastError() ;
		}

		memcpy ( lpMapAddr, lpNewMapAddr, dwCurPart ) ;
		FlushViewOfFile ( lpMapAddr, dwCurPart ) ;

		UnmapViewOfFile ( lpMapAddr ) ;
		UnmapViewOfFile ( lpNewMapAddr ) ;
		CloseHandle ( hNewMapFile ) ;
		CloseHandle ( hNewFile ) ;
	}

	CloseHandle ( hMapFile ) ;
	CloseHandle ( hFile ) ;

	this->DeleteAllPartFiles ( pItem->szFileName ) ;

	return 0 ;
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (16)
雪    币: 2384
活跃值: (766)
能力值: (RANK:410 )
在线值:
发帖
回帖
粉丝
2
北极星兄又出手了,学习。
2006-8-11 22:12
0
雪    币: 47147
活跃值: (20460)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
3
北极星的文章喜欢看
2006-8-11 22:14
0
雪    币: 603
活跃值: (617)
能力值: ( LV12,RANK:660 )
在线值:
发帖
回帖
粉丝
4
太强了太强了!
2006-8-11 22:45
0
雪    币: 415
活跃值: (34)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
5
呵.呵.随然看过,得支持一下,,
2006-8-11 23:35
0
雪    币: 139
活跃值: (126)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
6
MSDN:

To guard against an access violation, use structured exception handling to protect any code that writes to or reads from a memory mapped view. For more information, see Reading and Writing From a File View.

To have a mapping with executable permissions, an application must call CreateFileMapping with either PAGE_EXECUTE_READWRITE or PAGE_EXECUTE_READ, and then call MapViewOfFile with FILE_MAP_EXECUTE | FILE_MAP_WRITE or FILE_MAP_EXECUTE | FILE_MAP_READ.

Example:

DWORD dwLength;

__try
{
   dwLength = *((LPDWORD) lpMapAddress);
}
__except(GetExceptionCode()==EXCEPTION_IN_PAGE_ERROR ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
   // Failed to read from the view.
}

__try
{
   *((LPDWORD) lpMapAddress) = dwLength;
}
__except (GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR ?
             EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
        // Failed to write to the view.
}
2006-8-12 01:22
0
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
7
Thanks for your suggest!
I havn't got the level of normalization, but i'll try my best to improve this condition!
2006-8-12 10:55
0
雪    币: 260
活跃值: (81)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
今天才看到,一定要顶
2006-8-12 11:08
0
雪    币: 234
活跃值: (370)
能力值: ( LV9,RANK:530 )
在线值:
发帖
回帖
粉丝
9
这个一定要顶的
2006-8-12 11:50
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
强支持一下
2006-8-12 12:01
0
雪    币: 179
活跃值: (131)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
11
留名以后定要学习
2006-8-13 01:04
0
雪    币: 750
活跃值: (228)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
12
学习.....
2006-8-13 17:51
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
dddddddddd
2006-8-13 18:04
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
好帖就得顶,已收藏!
2006-8-14 11:21
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
真的很不错啊,又有了好大的收获
2006-10-14 03:34
0
雪    币: 538
活跃值: (32)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
进来学习学习
2006-10-14 10:19
0
雪    币: 139
活跃值: (126)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
17
Windows在做File Mapping的时候,是通过Windows memory manager创建一个section object,同时分配一块virtual address space里的memory block。一般有两类section object:

pagefile-based:作为进程间共享数据用,并且可以映射到任何地址,包括user space和kernel space。

file-based:方便对文件的访问。好像从Windows XP开始,拷贝小于32KB的文件,系统实际上是通过基于文件的memory mapping来实现的。
2006-10-14 15:37
0
游客
登录 | 注册 方可回帖
返回
//