關於Windows文件讀寫_暗涌_新浪博客

關於Windows文件讀寫_暗涌_新浪博客html

    這幾天在研究怎麼才能加快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    //用於複製文件句柄
);windows

對於讀寫速度,最重要的是dwFlagsAndAttributes參數,這個參數的取值能夠參看MSDN,這裏稍微說一下:
 

Attributes:
該參數能夠接收下列屬性的任意組合.除非其它全部的文件屬性忽略FILE_ATTRIBUTE_NORMAL.
FILE_ATTRIBUTE_ARCHIVE 文件將被存檔,程序使用此屬性來標誌文件去備份或移除緩存

FILE_ATTRIBUTE_HIDDEN 文件被隱藏,它不會在通常文件夾列表中被裝載.安全

FILE_ATTRIBUTE_NORMAL 文件沒有被設置任何屬性.服務器

FILE_ATTRIBUTE_OFFLINE 文件的數據沒有被當即用到。指出正在脫機使用該文件。網絡

FILE_ATTRIBUTE_READONLY 這個文件只可讀取.程序能夠讀文件,但不能夠在上面寫入內容,也不可刪除.app

FILE_ATTRIBUTE_SYSTEM 文件是系統的一部分,或是系統專用的.異步

FILE_ATTRIBUTE_TEMPORARY 文件被使用後,文件系統將努力爲(文件的)全部數據的迅迅訪問保持一塊內存。臨時文件應當在程序不用時及時刪除。socket

 

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文件讀寫

相關文章
相關標籤/搜索