1、利用段在同一程序的多个实例之间共享数据
#include<iostream> using namespace std; #pragma data_seg("shared")//自定义端,名字为share volatile long g_instance=0;//存放在自定义段中的变量必须初始化否则不可放入 #pragma data_seg() #pragma comment(linker,"/Section:shared,RWS") //指定该段的属性为可读R可写W可共享S可运行E _declspec(allocate("shared")) int d;//可利用这种方式将未初始化的变量加入到自定义段中 void main() { cout<<"实例数:"<<++g_instance<< endl; getchar(); --g_instance; }
2、使用内存映射文件
使用这种方法可以把文件映射到内存中,这样我们就不用在分配任何内存,而全部交给操作系统来做
#include <Windows.h>#include <string>#include <iostream>using namespace std ;void main (){HANDLE hFile = CreateFile ( "d://r.txt" , GENERIC_WRITE | GENERIC_READ , 0 , NULL , OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , NULL ); //打开文件DWORD dwFileSize=GetFileSize(hFile,NULL);//获得文件大小HANDLE hFileMap=CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,dwFileSize+sizeof(char),NULL);//创建一个文件内核对象PVOID pvFile=MapViewOfFile(hFileMap,FILE_MAP_WRITE,0,0,0);//为文件的数据预定一块地址空间区域并将文件的数据作为物理存储器调拨给区域PSTR pch=(PSTR)pvFile;//这个指针包含了文件的所有内容,就好像所有文件内容都放入内存一样pch[dwFileSize/sizeof(char)]=0;//由于文件结尾不是‘0’,所以加上,便于进行字符串操作cout<<pch<<endl;_strrev(pch);//利用函数对字符串进行翻转cout<<pch<<endl;UnmapViewOfFile(pvFile);//从进程空间撤销对文件数据的关联CloseHandle(hFileMap);SetFilePointer(hFile,dwFileSize,NULL,FILE_BEGIN);SetEndOfFile(hFile);CloseHandle(hFile);}
3、通过多次内存映射文件来处理大文件
#include <Windows.h>#include <string>#include <iostream>using namespace std ;void main (){SYSTEM_INFO sinf ;GetSystemInfo (& sinf );HANDLE hFile = CreateFile ( TEXT ( "d://huge.txt" ), GENERIC_WRITE | GENERIC_READ , 0 , NULL , OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , NULL ); //打开文件DWORD dwFileSizeHigh;_int64 qwFileSize=GetFileSize(hFile,&dwFileSizeHigh);//获得文件大小qwFileSize+=(((_int64)dwFileSizeHigh)<<32);//将高32位加到文件低32位上HANDLE hFileMap=CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,0,NULL);//创建一个文件内核对象,大小默认为文件大小CloseHandle(hFile);_int64 qwFileOffset=0;//每次映射文件大小,初始值为0while(qwFileSize>0){DWORD dwBytesInBlock=sinf.dwAllocationGranularity;//预定空间的分配丽都if(qwFileSize<sinf.dwAllocationGranularity)dwBytesInBlock=(DWORD)qwFileSize;PCHAR pbFile=(PCHAR)MapViewOfFile(hFileMap,FILE_MAP_WRITE,(DWORD)(qwFileOffset>>32),//高32位(DWORD)(qwFileOffset&0xFFFFFFFF),//低32位dwBytesInBlock);//为文件的数据预定一块地址空间区域并将文件的数据作为物理存储器调拨给区域cout<<"content: "<<pbFile<<endl;UnmapViewOfFile(pbFile);//从进程空间撤销对文件数据的关联qwFileOffset+=dwBytesInBlock;qwFileSize-=dwBytesInBlock;}CloseHandle(hFileMap);}
4、内存映射文件和一致性
系统运行我们把同一个文件中的数据映射到多个视图中,但是数据也仍然是一致的,这是因为数据文件中的每个页面在内存中只有一份,但这些内存页面会被映射到多个进程的地址空间中。
5、以页交换文件为后备存储器的内存映射文件
系统创建以页交换文件为后备存储器的内存映射文件,就不必创建或打开一个专门的磁盘文件,因此不需要调用CreateFile。我们只需要像原来那样调用CreateFileMapping,并将INVALID_HANDLE_VALUE,作为hFile参数传入,这告诉系统创建的文件映射对象的物理存储器不是磁盘上的文件而是希望系统从页交换文件中调拨物理存储器。一旦创建了文件映射对象,并把一个视图映射到了进程的地址空间中,我们就可以像使用任何内存区域一样使用它。如果想要和其他进程共享数据,那么可以再调用
CreateFileMapping的时候将一个以0为终止符的字符串作为pszName参数传入。这样其他想要访问共享数据的进程就能够以同一个名称为参数来调用
CreateFileMapping,或Open
FileMapping,该区域可在进程间共享。
#include <Windows.h>#include <iostream>using namespace std ;void main (){HANDLE hFileMap = CreateFileMapping ( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE , 0 , 4 * 1024 , TEXT ( "share" ));PVOID pView = MapViewOfFile ( hFileMap , FILE_MAP_READ | FILE_MAP_WRITE , 0 , 0 , 0 );memcpy ( pView , "nihao" , 6 );cout <<( char *) pView << endl ;UnmapViewOfFile ( hFileMap );HANDLE hFileOpen = OpenFileMapping ( FILE_MAP_READ | FILE_MAP_WRITE , FALSE , TEXT ( "share" ));PVOID pViewOpen = MapViewOfFile ( hFileOpen , FILE_MAP_READ | FILE_MAP_WRITE , 0 , 0 , 0 );cout <<( char *) pViewOpen << endl ;UnmapViewOfFile ( pViewOpen );CloseHandle ( hFileOpen );}
6、稀疏调拨的内存映射文件
#include <Windows.h> #include <iostream> using namespace std ; typedef struct SOMEDATA { char data [ 5 * sizeof ( char )]; } SOMEDATA ,* PSOMEDATA ; void main () { HANDLE hMap = CreateFileMapping ( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE | SEC_RESERVE , 0 , 10 * 1024 , NULL ); //SEC_RESERVE只分配区域,不调拨内存 PSOMEDATA p =( PSOMEDATA ) MapViewOfFile ( hMap , FILE_MAP_WRITE | FILE_MAP_READ , 0 , 0 , 0 ); int index ; cin >> index ; VirtualAlloc (& p [ index ], sizeof ( SOMEDATA ), MEM_COMMIT , PAGE_READWRITE ); //用时分配 strcpy ( p [ index ]. data , "himan" ); cout << p [ index ]. data ; UnmapViewOfFile ( p ); //不可用VirtualAlloc来释放 CloseHandle ( hMap ); }