【轉載】dokan開發文件系統驅動注意事項

 

dokan是用戶態的文件系統驅動,可以稱之爲fuse for windows。可以用來開發虛擬磁盤,即在“我的電腦”中虛擬出一個硬盤來,可以是硬盤,也可以是可移動磁盤或者網絡硬盤。

CreateFile、FindFiles、GetFileInformation需要最優先實現,有了這兩個接口,就可以瀏覽目錄了。

進入CreateFile,需要判斷請求的虛擬文件是目錄還是文件,如果是目錄,則需要設置DokanFileInfo->IsDirectory爲True,並直接返回成功。虛擬文件的打開可以根據CreationDisposition、AccessMode、ShareMode三者組合。最簡單的做法是在最開始處對做判斷,因爲它只有五種可能性,把文件不存在,但卻需要以只讀打開的都排除,然後就可以放心地應用:讀使用”rb+”, 寫使用”wb+”。

Create中返回的文件描述符或者類似的數據可以保存DokanFileInfo->context中,這個值可以在以後的其它函數調用中訪問到:比如CloseFile, CleanUp, DeleteFile, ReadFile, WriteFile等等。

CreateDirectory和實際的文件操作一致。 
OpenDirectory一般直接返回成功,除非目錄無訪問權限,可以人爲地返回-1。 
CloseFile用處不大,因爲在CloseFile之前,有一道CleanUp調用,已經清除了打開的文件。 
CleanUp和CloseFile好像會被一前一後地調用,在CleanUp中需要做的事情是根據DokanFileInfo->context保存的值關閉虛擬文件。並且DokanFileInfo->DeleteOnClose如果爲True,則需要把當前請求的文件或者目錄刪除。文件刪除的動作實際是在Cleanup中實現的。

DeleteDirectory和DeleteFile兩個接口實現中,不能夠真正去刪除文件,而是在文件或者目錄需要刪除時,返回0即可,系統會繼續調用上面說的cleanup來處理刪除事件。

在文件的刪除時,有可能操作系統傳遞過來的請求文件並未被關閉,但好在同時DokanFileInfo->context也會被一同傳遞來,所以可以先強行關閉打開的文件,然後做刪除操作。

操作系統的應用程序每次讀寫文件都是通過ReadFile、WriteFile接口完成的,一般情況下一次求請的大小比較小,比如65535Bytes等,但也有例外,比如使用FastCopy等多線程文件快速複製工具時,它會直接向ReadFile請求32MB的大小。

ReadFile WriteFile一般情況下都會有DokanFileInfo->context參數傳進來,就像平常我們寫文件讀寫的代碼一樣,總是先fopen個FILE*出來,然後再讀寫。 但是也有例外,比如記事本在讀文件的時候,就只是給個路徑+文件名。 這個時候,需要在ReadFile WriteFile臨時專門爲這一次請求打開文件,在退出函數時,一定要關閉它。

FlushFileBuffers是個沒用的東西,可以不實現。

GetFileInformation非常重要,資源管理器每次打開目錄時,會查詢當前目錄每個文件的信息。如果給出的信息不恰當,比如文件時間如果是個變化的值(比如圖省事,將所以文件的時間設置爲當前時間),這樣會導致系統不斷地查詢,非常的恐怖。 在返回的dwFileAttributes中,需要小心地設置文件類型,文件和目錄千萬要區別正確。 試過FILE_ATTRIBUTE_NORMAL+FILE_ATTRIBUTE_ARCHIVE-FILE_ATTRIBUTE_ENCRYPTED以及FILE_ATTRIBUTE_DIRECTORY就基本正常工作了,FILE_ATTRIBUTE_ENCRYPTED一定要去掉,不然系統會認爲你虛擬出來的盤符是加密的,往其它盤複製文件時會提示不能處理加密文件而直接失敗。

FindFiles函數中,我們需要用傳遞進來的函數指針FillFindData將我們需要顯示的目錄和文件填充到系統爲我們準備好的地方。只要文件的屬性dwFileAttributes像樣,可以構造虛擬文件和目錄(比如可以將數據庫裏的用戶和組記錄讀出來,表示成一層層的目錄)。

MoveFile就是移動文件及改名,沒什麼特殊的地方。

SetEndOfFile一般情況下使用不到,但是如果有軟件調用了這個API則還是有用的,比如像fastCopy,爲了儘可能地加快複製速度,它每次從內存將固定大小的數據保存到硬盤,比如大小爲31MB的文件,實際上它寫了32MB(文件尾部的數據其實是多餘的),這是用readFile WriteFile實現的。但它最後會根據原文件的真實大小來做一次setEndOfFile將其裁剪到正確的大小。如果不實現setEndOfFile,fastcopy就沒用了。

SetFileAttributes和SetFileTime如果不想實現,就讓它返回0,最好不要爲了禁用這兩個api.因爲像Word之類的軟件,它很在意這兩個函數,在保存文件時候不厭其煩地調用,所以爲了讓Word在虛擬盤上工作正常,必須忽悠它,否則不能保存做過編輯的文檔。

GetDiskFreeSpace是返回驅動器的容量信息的,比如虛擬盤可以做容量限制。 
GetVolumeInformation返回驅動器的卷標和文件系統類型,可以隨便設置,文件類型可以隨便取名,比如“XX文件系統”,和NTFS/FAT32是同等地位的。

GetFileInformation 有時候傳遞過來的DokanFileInfo->context不是空的,所以一定要使用它來查詢文件大小。 假設DokanFileInfo->context保存的是fopen打開的fd, 如果使用傳遞過來的文件名去GetFileAttribute或者Stat()真實文件,有可能會因爲緩存的緣故查詢到的文件大小不是實時的。這一點在對文件大小變化敏感的軟件上特別重要,比較變態的Word,在保存的時候,它會先保存到臨時文件,保存過程中,寫一點數據,馬上查詢文件大小是否有變化是否和寫的數據大小一致。如果這時GetFIleInformation馬馬虎虎地返回個大小,Word就**了,它會以爲當前磁盤是不穩定的,或者容量比較用光,而拒絕保存。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章