• 第十七章 内存映射文件


    //1.
    (A):与虚拟内存相似,内存映射文件允许开发人员预订一块地址空间区域并给区域调拨物理存储器。不同之处在于,内存映射文件的物理存储器来自磁盘上已有的文件,而不是来自系统的页交换文件。
    一旦把文件映射到地址空间,我们就可对它进行访问,就像整个文件都已被载入内存一样
    (B):内存映射文件主要用于以下三种情况:
    	(1):系统使用内存映射文件来载入并运行.exe和DLL文件。节省了页交换文件的空间及应用程序启动的时间。
    	(2):开发人员可用内存映射文件来访问磁盘上的数据文件。可避免直接对文件进行I/O操作和对文件内容进行缓存。
    	(3):通过使用内存映射文件,我们可以在一台机器的不同进程之间共享数据,此方法是在同一台机器不同进程间共享数据的最高效方法
    
    //2.
    (A):当一个线程调用了 CreateProcess 的时候,系统会执行以下步骤:
    	(1):系统会确定 CreateProcess 所指定exe所在的位置,若无法找到该exe文件,系统不会创建进程, CreateProcess 返回 FALSE
    	(2):系统创建一个新的进程内核对象。
    	(3):系统为新进程创建一个私有地址空间
    	(4):系统预定一块足够大的地址空间来容纳exe文件。待预定的地址空间区域的具体位置已经在exe文件中指定。默认情况下exe文件的基地址是0x00400000(在64位windows下的64位程序来说可能会不同),
    		但是若在链接时使用 /BASE 链接器开关,就可以自己给应用程序指定不同的地址。
    	(5):系统会对地址空间区域进行标注,表明该区域的后备物理存储器来自磁盘上的exe文件,而并非来自系统的页交换文件。
    (B):系统将exe映射到进程地址空间以后会访问exe文件中的一个段,这个段列出了一些DLL文件,包含了exe文件调用到的函数。然后系统会调用 LoadLibrary 来加载入每一个DLL,如果DLL还需要调用到其他DLL,系统同样会使用 LoadLibrary 来载入,
    此过程执行的操作如下:
    	(1):系统会预定一块足够大的地址空间区域来容纳DLL文件。待预定地址空间区域的具体位置在DLL文件中已经指定。默认情况下, Microsoft 会将 x86 平台的DLL的基地址设为 0x10000000 ,将 x64 平台的DLL基地址是0x00400000
    		也可以使用 /BASE 链接器开关来设定。与系统一起发布的DLL都具有不同的基地址,这样即使把他们都加在到同一个进程的地址空间,也不会发生重叠。
    	(2):如果系统无法在DLL文件中指定的基地址处预定区域,可能是因为该区域已经被别的DLL或exe占用,也可能是区域不够大,系统会尝试在另一个地址来为DLL预定地址区域。
    	(3):系统会对地址空间区域进行标注,表明该区域的后备物理存储器来自磁盘上的DLL文件,而非来自系统的页交换文件。如果Windows不能将DLL载入到指定的基地址而必须重定位的话,系统还会另外进行标注,表明DLL中有一部分存储器被映射到了页交换文件。
    (C):如果因为某些原因无法将exe文件和所需DLL映射到地址空间区域,系统会先给用户显示一个对话框,然后释放进程地址空间和进程内存对象。 CreateProcess 返回 FALSE
    (D):所有exe文件和DLL文件都映射到进程地址空间以后,系统会开始执行exe文件的启动代码。当完成对exe文件的映射以后,系统会负责所有换页,缓存以及高速缓存操作。
    
    //3.
    (A):如果一个应用程序已经在运行,那么当我们为这个应用程序创建一个新的进程时,系统只不过是打开另一个内存映射视图,创建一个新的进程内核对象,并(主线程)创建一个新的线程对象。
    通过内存映射文件,同一个应用程序的多个实例可以共享内存中的代码和数据。
    (B):文件的内容被分为段。代码在一个段中,全局变量在另一个段中。段会对齐到页面大小的整数倍。在exe或DLL文件中,代码段通常在数据段前面
    (C):当应用程序的一个实例修改了数据页面的一些全局变量后,系统会使用写时复制,致使应用程序的其他实例不受影响
    在调试一个应用程序的时候,我们用调试器设置一个断点,这时调试器会修改我们的代码,此时也会触发写时复制的特性,致使应用程序的其他实例不受影响
    
    //4.
    (A):默认情况下,同一个exe或DLL的多个实例不会共享全局或静态数据,当其中一个实例更改了全局变量或静态数据时,会触发写时复制特性。
    (B):段属性:
    	(1):READ:可以从该段读取数据
    	(2):WRITE:可以向该段写入数据
    	(3):EXECUTE:可以执行该段的内容
    	(4):SHARED:该段的内容为多个实例所共享(这个属性实际上关闭了写时复制的机制)
    (C):dumpBin工具 指定 /headers 来查看exe或DLL文件的各个段
    实例:
    #include <string>
    
    using std::string;
    
    #pragma data_seg("SZN")	//创建自己的段
    int nValue = 1024;
    string str = "123";
    int nTem;				//编译器只会将已初始化的变量保存在这个段中,未初始化的变量不会放入指定段中
    #pragma data_seg()		//停止把已初始化的变量放入指定的段,转而将其放入默认数据段
    
    #pragma comment(linker, "/SECTION:SZN,RWS")	//设定段的属性,R:read W:write S:share,并将链接器开关嵌入源代码中
    __declspec(allocate("SZN")) int nAddValue;	//此句代码允许我们将未初始化代码放入指定段,指定的段必须存在
    
    int main()
    {
    	printf("nValue = %d, str = %s, nTem = %d, nAddValue = %d
    ", nValue, str.c_str(), nTem, nAddValue);
    
    	++nValue;
    	str += "0";
    	++nTem;
    	++nAddValue;
    
    	system("pause");
    	return 0;
    }
    //第一次运行输出:nValue = 1024, str = 123, nTem = 0, nAddValue = 0
    //第二次运行输出:nValue = 1025, str = 123, nTem = 0, nAddValue = 1
    
    上述代码生成的可执行 用dumpBin查看:
    C:Usersszn>"C:Program Files (x86)Microsoft Visual Studio 10.0VCinamd64d
    	  umpbin.exe" /headers C:UserssznDesktopDelDelDebugDel.exe
    	  Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
    	  Copyright (C) Microsoft Corporation.  All rights reserved.
    
    	  Dump of file C:UserssznDesktopDelDelDebugDel.exe
    
    	  PE signature found
    
    	  File Type: EXECUTABLE IMAGE
    
    	  FILE HEADER VALUES
    	  14C machine (x86)
    	  8 number of sections
    	  5A9FF1CF time date stamp Wed Mar 07 22:06:07 2018
    	  0 file pointer to symbol table
    	  0 number of symbols
    	  E0 size of optional header
    	  102 characteristics
    	  Executable
    	  32 bit word machine
    
    	  OPTIONAL HEADER VALUES
    	  10B magic # (PE32)
    	  10.00 linker version
    	  8A00 size of code
    	  4600 size of initialized data
    	  0 size of uninitialized data
    	  111EA entry point (004111EA) @ILT+485(_mainCRTStartup)
    	  1000 base of code
    	  1000 base of data
    	  400000 image base (00400000 to 00421FFF)
    	  1000 section alignment
    	  200 file alignment
    	  5.01 operating system version
    	  0.00 image version
    	  5.01 subsystem version
    	  0 Win32 version
    	  22000 size of image
    	  400 size of headers
    	  0 checksum
    	  3 subsystem (Windows CUI)
    	  8140 DLL characteristics
    	  Dynamic base
    	  NX compatible
    	  Terminal Server Aware
    	  100000 size of stack reserve
    	  1000 size of stack commit
    	  100000 size of heap reserve
    	  1000 size of heap commit
    	  0 loader flags
    	  10 number of directories
    	  0 [       0] RVA [size] of Export Directory
    	  1E000 [      50] RVA [size] of Import Directory
    	  20000 [     459] RVA [size] of Resource Directory
    	  0 [       0] RVA [size] of Exception Directory
    	  0 [       0] RVA [size] of Certificates Directory
    	  21000 [     430] RVA [size] of Base Relocation Directory
    	  1A820 [      1C] RVA [size] of Debug Directory
    	  0 [       0] RVA [size] of Architecture Directory
    	  0 [       0] RVA [size] of Global Pointer Directory
    	  0 [       0] RVA [size] of Thread Storage Directory
    	  0 [       0] RVA [size] of Load Configuration Directory
    	  0 [       0] RVA [size] of Bound Import Directory
    	  1E234 [     1E4] RVA [size] of Import Address Table Directory
    	  0 [       0] RVA [size] of Delay Import Directory
    	  0 [       0] RVA [size] of COM Descriptor Directory
    	  0 [       0] RVA [size] of Reserved Directory
    
    
    	  SECTION HEADER #1
    	  .textbss name
    	  10000 virtual size
    	  1000 virtual address (00401000 to 00410FFF)
    	  0 size of raw data
    	  0 file pointer to raw data
    	  0 file pointer to relocation table
    	  0 file pointer to line numbers
    	  0 number of relocations
    	  0 number of line numbers
    	  E00000A0 flags
    	  Code
    	  Uninitialized Data
    	  Execute Read Write
    
    	  SECTION HEADER #2
    	  .text name
    	  89FB virtual size
    	  11000 virtual address (00411000 to 004199FA)
    	  8A00 size of raw data
    	  400 file pointer to raw data (00000400 to 00008DFF)
    	  0 file pointer to relocation table
    	  0 file pointer to line numbers
    	  0 number of relocations
    	  0 number of line numbers
    	  60000020 flags
    	  Code
    	  Execute Read
    
    	  SECTION HEADER #3
    	  .rdata name
    	  24BC virtual size
    	  1A000 virtual address (0041A000 to 0041C4BB)
    	  2600 size of raw data
    	  8E00 file pointer to raw data (00008E00 to 0000B3FF)
    	  0 file pointer to relocation table
    	  0 file pointer to line numbers
    	  0 number of relocations
    	  0 number of line numbers
    	  40000040 flags
    	  Initialized Data
    	  Read Only
    
    	  Debug Directories
    
    	  Time Type       Size      RVA  Pointer
    	  -------- ------ -------- -------- --------
    	  5A9FF1CF cv           43 0001B73C     A53C    Format: RSDS, {1D76314A-ED9E-4
    	  885-83FC-A19116E49448}, 21, C:UserssznDesktopDelDelDebugDel.pdb
    
    	  SECTION HEADER #4
    	  .data name
    	  5EC virtual size
    	  1D000 virtual address (0041D000 to 0041D5EB)
    	  200 size of raw data
    	  B400 file pointer to raw data (0000B400 to 0000B5FF)
    	  0 file pointer to relocation table
    	  0 file pointer to line numbers
    	  0 number of relocations
    	  0 number of line numbers
    	  C0000040 flags
    	  Initialized Data
    	  Read Write
    
    	  SECTION HEADER #5
    	  .idata name
    	  B8C virtual size
    	  1E000 virtual address (0041E000 to 0041EB8B)
    	  C00 size of raw data
    	  B600 file pointer to raw data (0000B600 to 0000C1FF)
    	  0 file pointer to relocation table
    	  0 file pointer to line numbers
    	  0 number of relocations
    	  0 number of line numbers
    	  C0000040 flags
    	  Initialized Data
    	  Read Write
    
    	  SECTION HEADER #6
    	  SZN name				//自定义的段
    	  130 virtual size
    	  1F000 virtual address (0041F000 to 0041F12F)
    	  200 size of raw data
    	  C200 file pointer to raw data (0000C200 to 0000C3FF)
    	  0 file pointer to relocation table
    	  0 file pointer to line numbers
    	  0 number of relocations
    	  0 number of line numbers
    	  D0000040 flags
    	  Initialized Data
    	  Shared
    	  Read Write
    
    	  SECTION HEADER #7
    	  .rsrc name
    	  459 virtual size
    	  20000 virtual address (00420000 to 00420458)
    	  600 size of raw data
    	  C400 file pointer to raw data (0000C400 to 0000C9FF)
    	  0 file pointer to relocation table
    	  0 file pointer to line numbers
    	  0 number of relocations
    	  0 number of line numbers
    	  40000040 flags
    	  Initialized Data
    	  Read Only
    
    	  SECTION HEADER #8
    	  .reloc name
    	  5E8 virtual size
    	  21000 virtual address (00421000 to 004215E7)
    	  600 size of raw data
    	  CA00 file pointer to raw data (0000CA00 to 0000CFFF)
    	  0 file pointer to relocation table
    	  0 file pointer to line numbers
    	  0 number of relocations
    	  0 number of line numbers
    	  42000040 flags
    	  Initialized Data
    	  Discardable
    	  Read Only
    
    	  Summary
    
    	  1000 .data
    	  1000 .idata
    	  3000 .rdata
    	  1000 .reloc
    	  1000 .rsrc
    	  9000 .text
    	  10000 .textbss
    	  1000 SZN
    
    //5.使用内存映射文件
    (A):
    HANDLE WINAPI CreateFileMapping
    (
    	__in     HANDLE hFile,
    	__in_opt LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
    	__in     DWORD flProtect,				//保护属性 PAGE_* ,必须与 CreateFile 中指定的权限相兼容
    	__in     DWORD dwMaximumSizeHigh,
    	__in     DWORD dwMaximumSizeLow,
    	__in_opt LPCWSTR lpName
    );
    Creates or opens a named or unnamed file mapping object for a specified file.
    
    If the function succeeds, the return value is a handle to the newly created file mapping object.
    If the object exists before the function call, the function returns a handle to the existing object 
    (with its current size, not the specified size), and GetLastError returns ERROR_ALREADY_EXISTS.
    If the function fails, the return value is NULL.
    
    hFile [in]
    A handle to the file from which to create a file mapping object.
    The file must be opened with access rights that are compatible with the protection flags that the flProtect parameter specifies. 
    It is not required, but it is recommended that files you intend to map be opened for exclusive access
    If hFile is INVALID_HANDLE_VALUE, the calling process must also specify a size for the file mapping object in the dwMaximumSizeHigh and dwMaximumSizeLow parameters.
    In this scenario, CreateFileMapping creates a file mapping object of a specified size that is backed by the system paging file instead of by a file in the file system.
    
    dwMaximumSizeHigh [in]
    The high-order DWORD of themaximum size of the file mapping object.
    
    dwMaximumSizeLow [in]
    The low-order DWORD of the maximum size of the file mapping object.
    If this parameter and dwMaximumSizeHigh are 0 (zero), the maximum size of the file mapping object is equal to the current size of the file that hFile identifies.
    An attempt to map a file with a length of 0 (zero) fails with an error code of ERROR_FILE_INVALID. 
    Applications should test for files with a length of 0 (zero) and reject those files.
    (B):
    LPVOID WINAPI MapViewOfFile
    (
    	__in HANDLE hFileMappingObject,		//A handle to a file mapping object. The CreateFileMapping and OpenFileMapping functions return this handle.
    	__in DWORD dwDesiredAccess,			//The type of access to a file mapping object, which determines the protection of the pages
    	__in DWORD dwFileOffsetHigh,		//A high-order DWORD of the file offset where the view begins.
    	__in DWORD dwFileOffsetLow,
    	__in SIZE_T dwNumberOfBytesToMap
    );
    Maps a view of a file mapping into the address space of a calling process.
    
    dwDesiredAccess [in]:
    FILE_MAP_ALL_ACCESS:
    A read/write view of the file is mapped. The file mapping object must have been created with PAGE_READWRITE or PAGE_EXECUTE_READWRITE protection.
    When used with the MapViewOfFile function, FILE_MAP_ALL_ACCESS is equivalent to FILE_MAP_WRITE.
    FILE_MAP_COPY:
    A copy-on-write view of the file is mapped. The file mapping object must have been created with PAGE_READONLY, PAGE_READ_EXECUTE, PAGE_WRITECOPY, 
    PAGE_EXECUTE_WRITECOPY, PAGE_READWRITE, or PAGE_EXECUTE_READWRITE protection.
    When a process writes to a copy-on-write page, the system copies the original page to a new page that is private to the process. 
    The new page is backed by the paging file. The protection of the new page changes from copy-on-write to read/write.
    When copy-on-write access is specified, the system and process commit charge taken is for the entire view because 
    the calling process can potentially write to every page in the view, making all pages private. The contents of the 
    new page are never written back to the original file and are lost when the view is unmapped.
    FILE_MAP_READ:
    A read-only view of the file is mapped. An attempt to write to the file view results in an access violation.
    The file mapping object must have been created with PAGE_READONLY, PAGE_READWRITE, PAGE_EXECUTE_READ, or PAGE_EXECUTE_READWRITE protection.
    FILE_MAP_WRITE:
    A read/write view of the file is mapped. The file mapping object must have been created with PAGE_READWRITE or PAGE_EXECUTE_READWRITE protection.
    When used with MapViewOfFile, (FILE_MAP_WRITE | FILE_MAP_READ) and FILE_MAP_ALL_ACCESS are equivalent to FILE_MAP_WRITE.
    
    Each of the preceding values can be combined with the following value.
    FILE_MAP_EXECUTE:
    An executable view of the file is mapped (mapped memory can be run as code). 
    The file mapping object must have been created with PAGE_EXECUTE_READ, PAGE_EXECUTE_WRITECOPY, or PAGE_EXECUTE_READWRITE protection.
    
    dwFileOffsetLow [in]:
    A low-order DWORD of the file offset where the view is to begin. The combination of the high and low offsets must specify an offset within the file mapping. 
    They must also match the memory allocation granularity of the system. That is, the offset must be a multiple of the allocation granularity. 
    To obtain the memory allocation granularity of the system, use the GetSystemInfo function, which fills in the members of a SYSTEM_INFO structure.
    
    dwNumberOfBytesToMap [in]:
    The number of bytes of a file mapping to map to the view. All bytes must be within the maximum size specified by CreateFileMapping.
    If this parameter is 0 (zero), the mapping extends from the specified offset to the end of the file mapping.
    
    Mapping a file makes the specified portion of a file visible in the address space of the calling process.
    For files that are larger than the address space, you can only map a small portion of the file data at one time. When the first view is complete, 
    you can unmap it and map a new view.
    To obtain the size of a view, use the VirtualQuery function.
    Multiple views of a file (or a file mapping object and its mapped file) are coherent if they contain identical data at a specified time. 
    This occurs if the file views are derived from any file mapping object that is backed by the same file. 
    A process can duplicate a file mapping object handle into another process by using the DuplicateHandle function, 
    or another process can open a file mapping object by name by using the OpenFileMapping function.
    With one important exception, file views derived from any file mapping object that is backed by the same file are coherent or identical at a specific time.
    Coherency is guaranteed for views within a process and for views that are mapped by different processes.
    The exception is related to remote files. Although MapViewOfFile works with remote files, it does not keep them coherent. For example, 
    if two computers both map a file as writable, and both change the same page, each computer only sees its own writes to the page. 
    When the data gets updated on the disk, it is not merged.
    A mapped view of a file is not guaranteed to be coherent with a file that is being accessed by the ReadFile or WriteFile function.
    
    
    MapViewOfFileEx:
    Maps a view of a file mapping into the address space of a calling process. A caller can optionally specify a suggested base memory address for the view
    (C):
    BOOL WINAPI FlushViewOfFile
    (
    	__in LPCVOID lpBaseAddress,
    	__in SIZE_T dwNumberOfBytesToFlush	//会向上取整为页面大小的整数倍
    );
    Writes to the disk a byte range within a mapped view of a file.
    
    lpBaseAddress [in]
    A pointer to the base address of the byte range to be flushed to the disk representation of the mapped file.
    
    dwNumberOfBytesToFlush [in]
    The number of bytes to be flushed. If dwNumberOfBytesToFlush is zero, the file is flushed from the base address to the end of the mapping.
    
    If the function succeeds, the return value is nonzero.If the function fails, the return value is zero.
    (D):
    BOOL WINAPI UnmapViewOfFile(__in LPCVOID lpBaseAddress);
    Unmaps a mapped view of a file from the calling process's address space.
    
    lpBaseAddress [in]
    A pointer to the base address of the mapped view of a file that is to be unmapped. 
    This value must be identical to the value returned by a previous call to the MapViewOfFile or MapViewOfFileEx function.
    
    If the function succeeds, the return value is nonzero.If the function fails, the return value is zero. 
    (E):
    #include <Windows.h>
    #include <assert.h>
    
    int main()
    {
    	HANDLE hFile = INVALID_HANDLE_VALUE;
    	HANDLE hFileMap = NULL;
    
    	do 
    	{
    		hFile = CreateFile(TEXT("Test.dat"), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
    		if (INVALID_HANDLE_VALUE == hFile)
    		{
    			break;
    		}
    		char buff[260] = {};
    		for (int i = 0; i < 65536; ++i)
    		{
    			memcpy(buff, &i, sizeof i);
    			for (int j = 4; j < 260; ++j)
    			{
    				buff[j] = j - 4;
    			}
    
    			DWORD nTem = 0;
    			if (!WriteFile(hFile, buff, sizeof buff, &nTem, nullptr) || nTem != sizeof buff)
    			{
    				break;
    			}
    		}
    
    		hFileMap = CreateFileMapping(hFile, nullptr, PAGE_READWRITE, 0, 0, nullptr);
    		if (!hFileMap)
    		{
    			break;
    		}
    
    		void* pContent = MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);	//即可用 pContent 直接访问文件,就像文件已经全被载入到内存中一样
    		if (!pContent)
    		{
    			break;
    		}
    
    		*static_cast<char*>(pContent) = 6;										//文件被修改
    		if (!FlushViewOfFile(pContent, 4096))
    		{
    			assert(false);
    		}
    
    		if (!UnmapViewOfFile(pContent))
    		{
    			break;
    		}
    	} while (false);
    
    	if (INVALID_HANDLE_VALUE != hFile)
    	{
    		CloseHandle(hFile);
    	}
    
    	if (hFileMap)
    	{
    		CloseHandle(hFileMap);
    	}
    }
    
    //6.
    (A):系统允许我们将同一个文件中的数据映射到多个视图中。只要我们映射的是同一个文件映射对象,那么系统会确保各视图的数据是一致的,如果多个进程把同一个数据文件映射到多个视图中,
    数据也仍会是一致的,这是因为数据文件中的每个页面在内存中只存在一份,但是这些内存页面被映射到了多个地址空间中,仅此而已
    (B):在使用内存映射文件的时候,最好对打开的文件进行独占,否则当文件在别处被修改时,使用了内存映射文件的程序是不会得到通知的
    (C):
    //进程间共享数据
    #include <Windows.h>
    
    int main()
    {
    	HANDLE hFileMap = NULL;
    
    	do 
    	{
    		hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, 4096, TEXT("HelloWorld"));
    		//以页交换文件为后备存储器的内存映射文件
    
    		if (!hFileMap)
    		{
    			printf("Error
    ");
    			break;
    		}
    
    		void* pContent = MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
    		if (!pContent)
    		{
    			printf("Error
    ");
    			break;
    		}
    
    		++*static_cast<char*>(pContent);
    
    		if (!FlushViewOfFile(pContent, 4096))
    		{
    			printf("Error
    ");
    			break;
    		}
    
    		printf("%d
    ", *static_cast<char*>(pContent));
    
    		if (!UnmapViewOfFile(pContent))
    		{
    			printf("Error
    ");
    			break;
    		}
    	} while (false);
    
    	system("pause");
    
    	if (hFileMap)
    	{
    		CloseHandle(hFileMap);
    	}
    }
    打开上述代码生成的可执行文件,且不要进行关闭,则
    第一个exe输出:1
    第二个exe输出:2
    第三个exe输出:3
    第四个exe输出:4
    然后关闭所有exe,再重新打开,第一个exe又会输出1
    (D):
    //稀疏调拨的内存映射文件
    #include <Windows.h>
    
    int main()
    {
    	HANDLE hFileMap = NULL;
    
    	do 
    	{
    		hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE | SEC_RESERVE, 0, 4096 * 10, TEXT("HelloWorld"));
    		//稀疏调拨的内存映射文件
    
    		//SEC_RESERVE参考资料:https://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx
    
    		if (!hFileMap)
    		{
    			printf("Error
    ");
    			break;
    		}
    
    		char* pContent = reinterpret_cast<char*>(MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0));
    		if (!pContent)
    		{
    			printf("Error
    ");
    			break;
    		}
    
    		//pContent[0] = 1;				//没有指定物理存储器,会运行出错
    
    		auto pTem = VirtualAlloc(pContent, 4096, MEM_COMMIT, PAGE_READWRITE);
    		if (pContent != reinterpret_cast<char*>(pTem))
    		{
    			printf("Error
    ");
    			break;
    		}
    
    		pContent[0] = 1;
    
    		printf("%d
    ", pContent[0]);	//输出1
    
    		if (!UnmapViewOfFile(pContent))
    		{
    			printf("Error
    ");
    			break;
    		}
    	} while (false);
    
    	if (hFileMap)
    	{
    		CloseHandle(hFileMap);
    	}
    }
    

      

  • 相关阅读:
    重谈MST及Kruskal算法
    小技巧—边权转点权
    JDOJ 1062 过路费
    总结—二分答案求解问题
    CF10D LCIS
    NOIP 2012 摆花
    SDOI 2014 旅行
    CF550C Divisibility by Eight
    CF295C Greg and Friends
    USACO Closing the Farm
  • 原文地址:https://www.cnblogs.com/szn409/p/8531216.html
Copyright © 2020-2023  润新知