zoukankan      html  css  js  c++  java
  • 关于Windows文件读写_暗涌_新浪博客

    关于Windows文件读写_暗涌_新浪博客

        这几天在研究怎么才能加快windows文件读写速度,搜了很多文章,MSDN也看了不少。稍微给大家分享一下。
        限制windows文件读写速度的瓶颈其实最终还是来源于我们硬盘的固有特性,磁盘本身的转速和硬盘的串行化工作机制。我们所能做的只是改善软件实现方法去逼近硬盘的极限读写速度。平时我们在拷贝粘贴文件的时候,其实是用的windows本身的实现,其中有一个很大的影响速度的地方就是它们都用了windows的文件缓存机制,当你拷贝一个大文件时,windows会根据你要拷贝的文件大小缓存很大一部分到系统缓存,这时候你会看到系统缓存瞬间飙涨,机器性能大大降低。整体拷贝速度为10M/S左右。而IDE 7200转的硬盘读写速度一般能达到30M/S左右,所以浪费了很大一部分硬盘读写速度。而当我们并行读写多个文件时,速度比串行读写多个文件还要慢,这就是因为硬盘串行工作机制的限制,多文件并行操作时,时间都花在磁头摆动上了。并且在缓存读取上,命中率也将大大降低。所以我们要避免使用windows缓存机制,并尽量不要同时读写多段文件,尽量读写连续的文件块。
        一般来说,我们操作一个windows I/O句柄用的是windows文件读写系列API:CreateFile, ReadFile, WriteFile等,这些API不仅可以读写文件句柄,所有的I/O设备句柄都能通过这些API来操作。比如socket描述符, 串口描述符,管道描述符等。通过设置他们的参数,我们可以选择以不同的方式操作IO。例如CreateFile,原型如下:

    HANDLE CreateFile(
     LPCTSTR lpFileName,    //指向文件名的指针
     DWORD dwDesiredAccess,    //访问模式(写/读)
     DWORD dwShareMode,    //共享模式
     LPSECURITY_ATTRIBUTES lpSecurityAttributes, //指向安全属性的指针
     DWORD dwCreationDisposition,   //如何创建
     DWORD dwFlagsAndAttributes,   //文件属性
     HANDLE hTemplateFile    //用于复制文件句柄
    );

    对于读写速度,最重要的是dwFlagsAndAttributes参数,这个参数的取值可以参看MSDN,这里稍微说一下:
     

    Attributes:
    该参数可以接收下列属性的任意组合.除非其它所有的文件属性忽略FILE_ATTRIBUTE_NORMAL.
    FILE_ATTRIBUTE_ARCHIVE 文件将被存档,程序使用此属性来标志文件去备份或移除

    FILE_ATTRIBUTE_HIDDEN 文件被隐藏,它不会在一般文件夹列表中被装载.

    FILE_ATTRIBUTE_NORMAL 文件没有被设置任何属性.

    FILE_ATTRIBUTE_OFFLINE 文件的数据没有被立即用到。指出正在脱机使用该文件。

    FILE_ATTRIBUTE_READONLY 这个文件只可读取.程序可以读文件,但不可以在上面写入内容,也不可删除.

    FILE_ATTRIBUTE_SYSTEM 文件是系统的一部分,或是系统专用的.

    FILE_ATTRIBUTE_TEMPORARY 文件被使用后,文件系统将努力为(文件的)所有数据的迅迅访问保持一块内存。临时文件应当在程序不用时及时删除。

    Flags:

    可以接受下列标志的任意组合。

    FILE_FLAG_WRITE_THROUGH 

    指示系统通过快速缓存直接写入磁盘,

    FILE_FLAG_OVERLAPPED 

    指示系统初始化对象, 此操作将对进程设置一个引用计数并返回ERROR_IO_PENDING.处理完成后, 指定对象将被设置为信号状态.当你指定FILE_FLAG_OVERLAPPED时,读写文件的函数必须指定一个OVERLAPPED结构.并且. 当FILE_FLAG_OVERLAPPED被指定, 程序必须执行重叠参数(指向OVERLAPPED结构)去进行文件的读写. 这个标志也可以有超过一个操作去执行.

    FILE_FLAG_NO_BUFFERING  

    指示系统不使用快速缓冲区或缓存,当和FILE_FLAG_OVERLAPPED组合,该标志给出最
    大的异步操作量, 因为I/O不依赖内存管理器的异步操作.然而,一些I/O操作将会运行得长一些,因为数据没有控制在缓存中.     

    当使用FILE_FLAG_NO_BUFFERING打开文件进行工作时,程序必须达到下列要求:
      

    1. 文件的存取开头的字节偏移量必须是扇区尺寸的整倍数.
    2. 文件存取的字节数必须是扇区尺寸的整倍数.例如,如果扇区尺寸是512字节.程序就可以读或者写512,1024或者2048字节,但不能够是335,981或者7171字节.

    3. 进行读和写操作的地址必须在扇区的对齐位置,在内存中对齐的地址是扇区.尺寸的整倍数.一个将缓冲区与扇区尺寸对齐的途径是使用VirtualAlloc函数.它分配与操作系统内存页大小的整倍数对齐的内存地址.因为内存页尺寸和扇区尺寸--2都是它们的幂.这块内存在地址中同样与扇区尺寸大小的整倍数对齐.程序可以通过调用GetDiskFreeSpace来确定扇区的尺寸.

    FILE_FLAG_RANDOM_ACCESS
    指定文件是随机访问,这个标志可以使系统优化文件的缓冲.

    FILE_FLAG_SEQUENTIAL_SCAN 
    指定文件将从头到尾连续地访问.这个标志可以提示系统优化文件缓冲. 如果程序在
    随机访问文件中移动文件指针,优化可能不会发生;然而,正确的操作仍然可以得到保
    证. 指定这个标志可以提高程序以顺序访问模式读取大文件的性能, 性能的提高在许多程序读取一些大的顺序文件时是异常明显的.但是可能会有小范围的字节遗漏.

    FILE_FLAG_DELETE_ON_CLOSE

    指示系统在文件所有打开的句柄关闭后立即删除文件.不只有你指定了FILE_FLAG_DELETE_ON_CLOSE的文件。
    FILE_SHARE_DELETE
    如果没有使用FILE_SHARE_DELETE,后续的打开文件的请求将会失败.

    FILE_FLAG_BACKUP_SEMANTICS

    WINDOWS NT:指示系统为文件的打开或创建执行一个备份或恢复操作. 系统保证调
    用进程忽略文件的安全选项,倘若它必须有一个特权.则相关的特权则是SE_BACKUP_NAME和SE_RESTORE_NAME.你也可以使用这个标志获得一个文件夹的句柄,一个文件夹句柄能够象一个文件句柄一样传给某些Win32函数。

    FILE_FLAG_POSIX_SEMANTICS

    指明文件符合POSIX标准.这是在MS-DOS与16位Windows下的标准.

    FILE_FLAG_OPEN_REPARSE_POINT 

    指定这个标志制约NTFS分区指针.该标志不能够和CREAT_ALWAYS一起使用.

    FILE_FLAG_OPEN_NO_RECALL 

    指明需要文件数据,但是将继续从远程存储器中接收.它不会将数据存放在本地存储器中.这个标志由远程存储系统或等级存储管理器系统使用.

        可以看到,有很多标志和属性可以使用,但是这里最重要的对速度影响最大的是红字部分的FILE_FLAG_NO_BUFFERING和FILE_FLAG_OVERLAPPED.    

        FILE_FLAG_NO_BUFFERING就是说文件操作时不使用windows缓存机制,FILE_FLAG_OVERLAPPED则表示文件的操作将异步进行。就是说不等待I/O操作完成,读写函数便返回,这要用到重叠IO机制,自己针对IO状态做不同的事情,基本上用到的是GetOverlappedResult和WaitForMultiObject。

        当我单独使用FILE_FLAG_NO_BUFFERING时,拷贝粘贴一个400M文件大概22秒,接近20M/S的速度,但是指定FILE_FLAG_NO_BUFFERING时,文件位置,缓存大小,文件大小都有很大的限制,即都要和扇区大小对齐(见红字部分)。如果不这样,读写将失败。这的确增大了不少内存分配操作,但是速度提高却很明显。

        而当我使用FILE_FLAG_OVERLAPPED将文件分为多个部分同时读写时,发现速度反而慢了。回到开头说的,这就是硬盘本身的限制了。但是我参考Fastcopy(一个免费文件拷贝软件)源代码时,发现它也同时打开了多个文件读写。可是速度却没有慢多少。具体原因还得研究研究。

        以上都是在本地硬盘操作的情况下,没有网络的限制,而当我要在服务器上拷贝文件时,最大的瓶颈便成了网络。在这种情况下,我的想法是,服务器的硬盘读取速度应该大大高于我们的机器硬盘,所以可以将文件分多段同时读取,以争取网络带宽,而在写入时则以串行的方式写入连续的文件。这样既能充分利用网络,又能避免本地硬盘的读写速度限制。当然,具体效果还须回公司试验。关于Windows文件读写

  • 相关阅读:
    软件测试人员的年终绩效考核怎么应对
    收藏
    顶踩组件 前后两版
    订阅组件
    hdu 1963 Investment 完全背包
    hdu 4939 Stupid Tower Defense 动态规划
    hdu 4405 Aeroplane chess 动态规划
    cf 414B Mashmokh and ACM 动态规划
    BUPT 202 Chocolate Machine 动态规划
    hdu 3853 LOOPS 动态规划
  • 原文地址:https://www.cnblogs.com/sunleecn/p/3482486.html
Copyright © 2011-2022 走看看