我有个项目的需求如下, 
  1.实时存储大量的数据.每秒33个数据组,一个数据10M. 
  2.我测试用普通的fopen,fwrite系列函数,速度太慢. 
  3.我采用内存映射方法.即,产生文件-->建立映射--> 
    存储数据-->关闭句柄.   4.一切看起来都很正常,但是物理内存狂丢. 
  5.如果我在UnmapViewOfFile函数前加入FlushViewOfFile 
    则内存不丢失,但是速度慢很多。 我的问题是,为什么内存对狂丢.有无好的方法来快速产生大量的文件. 代码如下: 如果有高手解答解决了问题,兄弟狂给分.!!!! 
--------------------------------------------   ..... 
  case WM_TIMER:  //此定时器33秒调用一次. 
    WriteToDiskMapFile1();  //此函数就是生成映射文件. 
    break; 
  ...... 
BOOL WriteToDiskMapFile1() 
{ static int abc=0; abc++; //计算每次映射长度(根据一帧数据的长度,以整数大小倍数OS映射页面 一帧数据 
DWORD dwBlockBytes = 32*65536; char buf[128]; 
char fn[256]; memset(buf,0,128); 
memset(fn,0,256); 
sprintf(buf,"%d",abc); //映射文件名称.这里自动生成一个文件名称. 
strcpy(fn,"d:\\temp\\map"); 
strcat(fn,buf); 
strcat(fn,".dat"); //映射文件句柄. 
int ret;         //这里先生成一个文件. 
HANDLE handle = CreateFile(fn,GENERIC_READ ¦GENERIC_WRITE,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL); 
SetFilePointer(handle, dwBlockBytes, NULL, (DWORD)FILE_BEGIN); 
SetEndOfFile(handle); 
//产生映射文件. 
HANDLE map_handle = CreateFileMapping(handle,NULL,PAGE_READWRITE,0,0,NULL); 
CloseHandle(handle); 
handle = NULL; //映射视图 
LPBYTE lpbMapAddress = (LPBYTE)MapViewOfFile(map_handle,FILE_MAP_ALL_ACCESS, 
0, 
0, 

); //对映射的视图进行访问(模拟写数据) 
memset(lpbMapAddress,0x41,dwBlockBytes); //撤消文件映像 
//FlushViewOfFile(lpbMapAddress,0); -->关键点 
UnmapViewOfFile(lpbMapAddress); 
CloseHandle(map_handle); return TRUE; 

程序的每一行我都跟踪n遍了,不存在函数错误! 谢谢! 

解决方案 »

  1.   

    这是正常现象,物理内存是系统调度的,当你调用FlushViewOfFile时,系统会把物理内存中的数据写入文件,此后再UnmapViewOfFile时,系统就把内存直接释放掉了;如果没有调用FlushViewOfFile,直接调用UnmapViewOfFile时,系统不会立即把数据写入文件、释放物理内存,所以感觉速度很快,当系统物理内存资源不足或者程序结束或者主窗口最小化等时候,系统才会把数据写入文件,回收物理内存。
      

  2.   

    另外,经过我测试,即使不用FlushViewOfFile,文件内写入的数据也是正确的...
      

  3.   

    FlushViewOfFile只是告诉系统把数据立即回写到文件,不会影响正确性。
    目前没有问题,要解决什么?如果觉得速度不够快,需要从程序设计上考虑优化的方法。如果希望大家帮忙想办法,需要把程序的功能再描述具体一些。
      

  4.   

    我需要做一个实时的数据存储程序.数据源是一个网络,过来的数据已经保证每秒33帧,每一帧的大小是10M.要求存储程序必须能够及时存储数据到文件内.也就是说,程序必须保证每一帧的存储速度也是30ms以内(或者说即使达不到,也要大部分的情况下小于30ms).
      程序的设计我是想有一个CACHE,是一个队列,保证网络过来的数据先推进这个CACHE内.同时
    另一个存储线程再从这个队列内取出最先进入的数据.这样可以保证不丢数据.
      但问题是,如果写入磁盘的程序太慢.那就会出现始终无法保证数据全部存储到硬盘内的情况.
    好不容易搞了个映射,结果内存还有问题!   所以请教有无好的办法.
       我的最后的办法就是直接写磁盘.不过我不想这么做.有些麻烦.还得管理扇区!谢谢!
      如过各位能给解决或者提提好的思路,分数不是问题.多少都给!
      

  5.   

    你现在的问题已经不是单单从程序上就能解决的了,你需要每秒向硬盘写入330MB数据,而现在常见的SATA硬盘接口传输速率只有300MB/s,实际写入的速度会更慢,即使全速运转也不能满足你的要求。你现在首先要确定程序运行的硬件环境,如果硬盘配置达不到要求,就需要考虑用多台主机分别来储存数据。
      

  6.   

    对了,我每一帧的数据的大小是2M.不是10M.(我算错了)但在我测试过程中.2M每帧*30帧/秒,用我上面的代码是完全满足了.
    但就是在映射时,我发现即使做了UnmapViewOfFile(lpbMapAddress)
    和CloseHandle(map_handle),系统好像并没有把内存页面给释放掉,
    因为我会频繁产生内存映射文件.因此会出现系统物理内存很快丢失,但
    应用程序内存没有变化(从Task Manager中看到的)
      

  7.   

    我想问,有无方法将系统内存页给删除而不做FlushViewOfFile,我发现
    所谓映射如果加入这句话FlushViewOfFile,存储每一帧数据(即2M)也
    很慢(大约40~100ms,WINDOWXP,1.5G CPU).而且不用FlushViewOfFile,我生成的文件的数据也是对的.请各位高手帮帮忙!
      

  8.   

    上面其实说的很清楚了,FlushViewOfFile这个调用类似C下面flush函数,只是要求系统立即把缓存中数据写入硬盘。如果你不用,系统将以自己的方式写硬盘,对你数据正确性没有影响。
    效率其实和很多因素相关,就像你硬盘本身最大速率,网络编程中的带宽,这些都是单靠程序无法解决的。
      

  9.   

    如果你只是把从网络接收到的数据直接写入文件,用文件映射的方式效率并不高。最合适的方式应该是用CreateFile使用FILE_FLAG_NO_BUFFERING标志来打开文件,不过这种方式也不会大幅提高效率,因为访问硬盘本身需要的时间是无法从程序上来缩短的,只能尽量减少不必要的操作。
    你这个程序要求硬盘写入速度在66MB/s以上,我不确定你的硬盘是否具有这么高的速度,另外即使硬盘可以达到这个速度,由于需要长时间高负荷运转,普通的硬盘也是不行的,很快就会出现故障,应该用服务器专用硬盘,最好是硬盘阵列。
      

  10.   

    好的,谢谢,给cnzdgs的帖子加分了