Dokan[转]

原文地址:http://www.cnblogs.com/xxonehjh/p/3634889.html

因工作需要,最近与同事合作使用Dokan开发了一个虚拟磁盘的简单程序,初步实现了远程目录映射到本地虚拟磁盘的功能。

远程服务端是用Python写的,主要是将远程主机上的目录文件传给客戶端,在这里就不细说了。

Dokan客户端则由Delphi开发,其参考代码来自网络上的Delphi例子,比如Mirror Driver

本篇文章主要是Dokan开发过程的一些总结,所以不会对Dokan本身做介绍,与Dokan有关的资料及代码,请到google里搜索,或到Dokan的官方网站去下载(Dokan官网),源码是C语言的,应用例子有Ruby、.Net及C的。如果想要Delphi的例子代码,只能自己去找了。

刚开始时由于不清楚如何用Dokan来实现一个文件系统,所以需要做一些试验,结果一不小心就蓝屏了!悲剧啊,用XP系统已经好多年没遇到蓝屏了。几次蓝屏之后,终于受不了了,于是在VMWare里装了个虚拟机的XP,这下不怕蓝屏了,哈哈。强烈建议装个虚拟机来玩Dokan,否则刚开始的时候你会蓝屏N次!

为简单起见,我做的Dokan虚拟磁盘采用将远程目录缓存到本地目录的方法来实现,这样就不用自己维护一堆目录、文件的信息,只需要关注如何更新同步目录与文件就可以了。由于Dokan是多线程的,因此实现时需要做到线程安全;查看Dokan使用的结构类型,发现只有两个成员可以使用,即DOKAN_OPTIONS里的GlobalContext和DOKAN_FILE_INFO里的Context,其中GlobalContext只能用来存储全局的信息,比如存放线程实例的指针,这样一来,实际上就剩下 DOKAN_FILE_INFO里的Context 一个成员可以用来存储与文件有关的信息了,一般用它来存储文件指针。我这次实现没有自己定义类来管理目录与文件,而是直接利用缓存目录,因此只需要处理文件指针和是否需要更新文件两个信息就可以了,而 DOKAN_FILE_INFO里的Context是Int64的,在Win32里可以用32位存文件指针,另32位用来存储文件更新信息。

//以下来自于Dokan.pas里的定义

_DOKAN_OPTIONS = packed record
    DriveLetter: WCHAR; // Drive letter to be mounted
    ThreadCount: Word; // Number of threads to be used
    DebugMode: Boolean;
    UseStdErr: Boolean;
    UseAltStream: Boolean;
    UseKeepAlive: Boolean;
    GlobalContext: Int64; // User-mode filesystem can use this variable
end;
PDOKAN_OPTIONS = ^_DOKAN_OPTIONS;
DOKAN_OPTIONS = _DOKAN_OPTIONS;

TDokanOptions = _DOKAN_OPTIONS;
PDokanOptions = PDOKAN_OPTIONS;

_DOKAN_FILE_INFO = packed record
    Context: Int64; // User-mode filesystem can use this variable
    DokanContext: Int64; // Reserved. Don‘t touch this!
    DokanOptions: PDOKAN_OPTIONS;
    ProcessId: ULONG; // Process id for the thread that originally requested the I/O operation
    IsDirectory: Boolean; // Indicates a directory file
    DeleteOnClose: Boolean; // Delete when Cleanup is called
    PagingIo: Boolean; // Read or write is paging IO
    SynchronousIo: Boolean; // Read or write is synchronous IO
    Nocache: Boolean; // No caching
    WriteToEndOfFile: Boolean; // If true, write to the current end of file instead of Offset parameter
end;
PDOKAN_FILE_INFO = ^_DOKAN_FILE_INFO;
DOKAN_FILE_INFO = _DOKAN_FILE_INFO;

TDokanFileInfo = _DOKAN_FILE_INFO;
  PDokanFileInfo = PDOKAN_FILE_INFO;

研究了几天,发现只需要实现少数几个回调函数就可以了:

1.FindFiles: 在这个回调函数里可以实现从远程目录同步其下的所有目录及文件。当然也可以在OpenDirectory回调函数里做,但实际使用时我发现OpenDirectory调用太频繁,而FindFiles调用次数要少一些。

2.CreateDirectory: 在这个回调函数里可以实现同步创建远程目录。

3.DeleteDirectory: 实现同步删除远程目录。 

4.CreateFile: 这个回调函数调用极其频繁,每次操作目录文件(包括打开文件)时首先都会调到它,我在这里实现了从远程目录同步更新本地文件的内容。需要注意的是,在虚拟磁盘里新建文件时,为了能在Cleanup里正确同步到远程目录,必须记下来。我使用了以下代码来实现:

if not DokanFileInfo.IsDirectory and (CreationDisposition in [CREATE_NEW, OPEN_ALWAYS, CREATE_ALWAYS]) then begin
  MySetFileDate(DokanFileInfo, DateTimeToFileDate(Now)); //Cleanup里会判断FileDate来决定是否保存到远程目录
end;

5.WriteFile: 可用于指示文件是否已修改,和Cleanup配合,以便保存文件时能正确提交到远程服务器。需要注意的WriteFile可能会被调用多次,所以它并不适合提交修改,只能记录修改标志。

6.Cleanup: 同步删除远程目录中的文件及保存本地修改的文件到远程目录。实现时我发现,在Cleanup中判断DokanFileInfo.DeleteOnClose及DokanFileInfo.IsDirectory来删除目录的代码根本就不会走到(所以我在DeleteDirectory里实现删除目录的同步),而删除文件则没问题。

这里有一点需要注意:因为执行Cleanup之前,可能会多次调用CreateFile,比如记事本保存文档时就会执行两次CreateFile之后再调用Cleanup,所以我在Cleanup的最后执行MySetFileDate(DokanFileInfo, 0)来清空标志,而没有在CreateFile里清空标志。

7.MoveFile: 这个回调函数仅在移动虚拟磁盘里的文件到另一个虚拟磁盘目录中去时才触发,故实现在远程目录中同步移动文件后,就可以正常实现目录文件的移动了。由于操作多个目录文件时,Windows会每个目录文件分别调用相关操作,因此实现这个回调函数后,自然就实现了多个目录文件的移动。如果是从其他盘移动目录文件到虚拟磁盘或从虚拟磁盘移动目录文件到其他盘,都不会触发MoveFile这个回调函数;而目录文件改名,则会触发MoveFile这个回调函数。

实现时还有一个调试信息如何显示的问题,对控制台程序,可以直接写到控制台;而对带窗口的程序,可以写日志文件,也可以发Windows消息。我采用了SendMessage来处理调试信息,具体实现请参看下面的代码。

最终的实现是由一个线程来实现Dokan虚拟磁盘的,目录与文件的同步函数则放到一个单独的单元文件里,连接远程服务端则采用IndyTCPClient实现,传输采用了JSON,以便于和服务端的Python脚本通讯。

时间: 2024-08-24 16:55:10

Dokan[转]的相关文章

Dokan简介[转]

1.      Dokan Library 简介 Dokan Library 帮助程序员在windows系统下轻松建立用户级文件系统,不需要写设备驱动,其与FUSE(Linux user mode file system)类似. 2.      Dokan原理 Dokan Library包含以下部分:   - user-mode library (dokan.dll)  LGPL    - driver (dokan.sys)             LGPL    - control prog

Dokan官方说明文档

Dokan 库Copyright(c) Hiroki Asakawa http://dokan-dev.net/en 什么是Dokan库=====================================================================当你想要在Windows下创建一个新的文件系统的时候,比如,改进FAT或者NTFS,你需要开发一个文件系统驱动.在内核模式开发一个设备驱动是一个非常棘手的问题.通过使用Dokan库,你可以很轻松地创建一个属于你自己的文件系统,

使用dokan实现一个虚拟映射盘?来我们聊聊

缘起: 项目组一直在做网盘客户端(同步协作盘)的开发,产品进入市场,用户使用以后出现了很多问题.其中一个最大的问题就是,用户数据量很大(有很多公共库共享文档,部分用户数据量超百万),首次登陆要同步很长时间,且共享文档库文档变化时,所有用户都要同步,实时占用用户的资源,严重影响用户体验.(ps:我们使用精益项目管理,产品基本功能稳定以后,就给用户使用,不断优化迭代) 解决:问题来了,肿么办?一看是性能问题,项目组就排了前端后端性能测试和性能优化的计划,顺便说,客户端的性能优化是我做的.优化以后我们

windwos-sshfs

从 http://www.jianshu.com/p/d79901794e3d 转载 目的 最近因为需要在linux虚拟机里进行开发程序,虽然在linux里有超强的编辑器vim,但vim开发html前台代码并没有某些编辑器如sublime高效,在linux下使用sublime的话又要安装桌面环境,而且需要修复sublime在linux下不支持中文等一些问题.所以想要直接在windows下直接修改linux里的文件. 本来想通过sublime的sftp插件来提供支持,但经过寻找发现了更好的工具-s

winsshfs的快速入手

之前在公司使用mac ,并且通过mac下的osfuse和sshfs连接,直接将虚拟机的文件目录同步到了本地,并且可以进行实时操作修改,对于写项目,确实是省了很大一部分上传的精力. 于是在自己的win下也寻找这样的软件工具,点击下载 需要先下载Dokan依赖 ,然后下载安装winsshfs. 我的是win10系统,最新版本的1.6.1.13可以正常使用的. 具体配置上图   --------- 1.Add 2.设置要连接的主机参数(ip,username,password),直接使用的密码登录方式

windows平台是上的sublime编辑远程linux平台上的文件

sublime是个跨平台的强大的代码编辑工具,不多说. 想使用sublime完成linux平台下django站点的代码编辑工作以提高效率(原来使用linux下的vim效率较低,适合编辑一些小脚本). 下载linux平台下的Sublime_Text_2.0.2_x64.tar.bz2(http://www.sublimetext.com/) 解压使用: tar -xjvf Sublime_Text_2.0.2_x64.tar.bz2 cd Sublime\ Text\ 2/ 执行 ./sublim

win8.1通过sshfs挂载linux目录

sshfs的作用 ssfhs可以通过ssh方式将远程的服务器上硬盘挂载到本地硬盘,也就是说只有你的虚拟机支持ssh链接,你就可以将虚拟机的硬盘挂载到本地,然后采用本地的方式来操作硬盘里的文件. 安装win-sshfs 安装win-sshfs依赖Dokan,所以先安装Dokan再正常安装win-sshfs,其过程略过不表,但有点需注意,Dokan也许需要翻墙下载,我已经打包好.http://down.51cto.com/data/2296157 本人的环境是win8.1,Dokan是通过设置兼容V