利⽤dokan作虚拟磁盘开发

本文详细介绍了如何使用Dokan库在Windows上创建用户态文件系统驱动,允许开发者虚拟出硬盘、可移动磁盘或网络硬盘。重点讲解了关键接口如CreateFile、FindFiles、GetFileInformation的实现,以及如何处理文件的打开、读写、删除和文件信息获取。此外,还强调了正确设置文件属性和响应系统查询的重要性,确保虚拟文件系统能稳定、高效地工作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


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就罢⼯了,它
会以为当前磁盘是不稳定的,或者容量⽐较⽤光,⽽拒绝保存。
--------------------------------------------------------
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值