Dokan官方说明文档
Dokan 库
Copyright(c) Hiroki Asakawa http://dokan-dev.net/en
什么是Dokan库
=====================================================================
当你想要在Windows下创建一个新的文件系统的时候,比如,改进FAT或者NTFS,你需要开发一个文件系统驱动。在内核模式开发一个设备驱动是一个非常棘手的问题。通过使用Dokan库,你可以很轻松地创建一个属于你自己的文件系统,而不需要写一个设备驱动。Dokan库非常相思雨FUSE(Linux用户下的文件系统),但是工作在Windows环境下。
许可声明
===================================================================
Dokan库包括LGPL(宽松的GPL授权声明,表示开源代码可以用到非开源私有程序,译者注),MIT许可程序(和LGPL有些类似,编者注)
- 用户模式库(dokan.dll) LGPL
- 驱动(dokan.sys) LGPL
- 控制程序(dokanctl.exe) MIT
- 挂载服务(mounter.exe) MIT
- 样本程序(mirror.c) MIT
需要进一步的细节,请查看许可文件。
LGPL license.lgpl.txt
GPL license.gpl.txt
MIT license.mit.txt
你可以通过以下网址获取源码 http://dokan-dev.net/en/download
环境
====================================================================
Dokan库运行在 Windowx XP,2003,Vista,2008,7 x86 和 Windows 2003,Vista,2008,7 x64.
它是怎么工作的
====================================================================
Dokan库包括一个用户态DLL(dokan.dll)和一个内核模式文件系统驱动(dokan.sys)。一旦Dokan文件系统驱动安装好之后,你就可以创建和Windows下可以看见的普通的文件系统一样的文件系统了。这个被我们称之为文件系统级的应用程序可以利用Dokan库来创建文件系统。
用户态程序的文件操作请求(比如创建文件,读取文件,写文件。。。)将会被发送到Windows I/O子系统(运行在内核态),紧接着送到Dokan文件系统驱动(dokan.sys)。
通过使用Dokan用户态库(dokan.dll)提供的函数,文件系统程序能够注册回调函数到文件系统驱动中。
文件系统驱动将会调用这些回调例程(routines),为了能够响应它收到的请求。回调例程的结果会被送回到用户态程序。
比如,当Windows浏览器请求打开一个目录的时候,OpenDirectory请求会被送到Dokan文件系统驱动并且驱动会调用文件系统程序提供的OpenDirectory回调函数。这个例程的结果将被送到Windows浏览器,作为OpenDirectory请求的响应。因此,Dokan文件系统驱动扮演者一个基于用户程序和文件系统程序之间的一个代理角色。
这种处理方式的优点就是它允许开发者在用户态下开发文件系统,这样安全并且容易调试。
库的部件组成和安装
=======================================================================
当我们运行安装程序是,它会安装Dokan文件系统驱动(dokan.sys),注册Dokan挂载服务(mounter.exe)和一系列库。安装的文件详细清单如下:
系统文件夹/dokan.dll Dokan用户态库
系统文件夹/drivers/dokan.sys Dokan挂载服务
ProgramFiles文件夹/Dokan/DokanLibrary/mounter.exe Dokan挂载服务
ProgramFiles文件夹/Dokan/DokanLibrary/dokanctl.exe Dokan控制程序
ProgramFiles文件夹/Dokan/DokanLibrary/dokan.lib Dokan导入库
ProgramFiles文件夹\Dokan\DokanLibrary\dokan.h Dokan库头文件
ProgramFiles文件夹\Dokan\DokanLibrary\readme.txt 这个文件(你正在读的,译者注)
你可以使用控制面板的 Add/Remove 程序来卸载Dokan。卸载后,需要重启你的电脑。
怎样创建你的文件系统
======================================================================
创建文件系统,一个应用程序需要在DOKAN_OPERATIONS结构实现函数(在dokan.h中声明)。函数一旦实现,你就可以把DOKAN_OPERRATIONS作为参数调用DokanMain函数。
为了挂载文件系统,在DOKAN_OPERATIONS中的函数语义和WindowsAPI语义相似并且有相同的名字。这些函数的参数和相应的WindowsAPI相同。这些函数被很多的线程调用,所以他们需要保证线程安全,否则很多问题可能产生。
这些函数典型的以下面的顺序调用:
1、创建文件CreatFile(打开文件)
2、其他函数
3、清除Cleanup
4、关闭文件CloseFile
文件访问操作(展现目录,读取文件属性。。。)之前,经常需要调用文件创建函数(打开目录,创建文件。。。)。在另一方面,当CloseFile Windows API关闭文件的时候,Dokan文件系统驱动会调用清除函数Cleanup。当操作成功结束,每一个函数应该返回0,否则返回一个负数表示错误码。错误码和Windows系统错误码相反。比如当CreatFile不能打开文件,你应该返回-2(-1*ERROR_FILE_NOT_FOUND)。
每一个函数的最后一个参数是一个DOKAN_FILE_INFO结构:
typedef struct _DOKAN_FILE_INFO {
ULONG64 Context;
ULONG64 DokanContext;
ULONG ProcessId;
BOOL IsDirectory;
} DOKAN_FILE_INFO, *PDOKAN_FILE_INFO;
每个用户态的文件句柄(file handle)都和DOKAN_FILE_INFO结构相关。因此,如果相同的文件句柄已经使用,结构内容就不会改变。当CreatFile系统调用打开文件时,DOKAN_FILE_INFO结构就会创建;当CloseFile系统调用关闭文件时,这个结构就会销毁。
这个结构中每一个成员的意义如下:
Context:一个指定的值,由文件系统应用程序指定。文件系统程序可以自由的使用这个变量来存储在文件访问阶段的固定值(从创建文件到关闭文件)比如文件句柄等等。
DokanContext:保留,Dokan库使用。
ProcessId:打开文件进程的进程ID。
IsDirectory:判断打开的文件是否是一个目录。
其他的如下
int (*CreateFile) (
LPCWSTR, // FileName,文件名
DWORD, // DesiredAccess,需要访问
DWORD, // ShareMode,共享模式
DWORD, // CreationDisposition,创建意向
DWORD, // FlagsAndAttributes,标识和属性
PDOKAN_FILE_INFO);
int (*OpenDirectory) (
LPCWSTR, // FileName
PDOKAN_FILE_INFO);
int (*CreateDirectory) (
LPCWSTR, // FileName
PDOKAN_FILE_INFO);
当变量IsDirectory设置为TRUE,操作的文件是目录。当IsDirectory时FALSE时,如果当前的操作是对目录操作,则写文件系统程序的程序员需要把它设置为TRUE。如果IsDirectory的值是FALSE,但是当前操作不是对目录操作,则程序员不需要更变该值。需要注意的是,当访问目录时,把IsDirectory的值设置为TRUE对于Dokan库而言是非常重要的。如果它没有被准确的设定,那么Dokan库将不知道这个操作是作用于目录,会带来许多问题。如果CreationDisposition 设定为 CREATE_ALWAYS 或者OPEN_ALWAYS 并且当前文件已经存在,那么CreatFile函数需要返回ERROR_ALEADY_EXISTS(183)
int (*Cleanup) (
LPCWSTR, // FileName
PDOKAN_FILE_INFO);
int (*CloseFile) (
LPCWSTR, // FileName
PDOKAN_FILE_INFO);
当Windows API提供的CloseHandle函数一旦执行,Cleanup函数将被调用。当函数CreateFile被调用的时候,如果文件系统程序在Context变量中存放了文件句柄,这个将在Cleanup函数中关闭,而不是CloseFile函数。
如果用户态程序调用CloseHandle,并且马上打开相同的文件,那么文件系统程序CloseFile函数在CreatFile API被调用之前可能不会被调用。这有可能引发共享问题。
值得注意的是:当用户使用内存映射文件时,WriteFile或者ReadFile函数可能Cleanup之后会被调用,这是为了完成I/O操作。文件系统应用也应该在这种情况下正常运行。
int (*FindFiles) (
LPCWSTR, // PathName,路径名
PFillFindData, //调用此函数时, 使用PWIN32_FIND_DATAW作为参数
PDOKAN_FILE_INFO); // (see PFillFindData definition)
// 你应该实现 FindFiles 或者 FindFilesWithPattern
int (*FindFilesWithPattern) (
LPCWSTR, // PathName,路径名
LPCWSTR, // SearchPattern,查询方式
PFillFindData, // call this function with PWIN32_FIND_DATAW
PDOKAN_FILE_INFO);
调用FindFiles或者FindFilesWithPattern函数是为了相应目录列表请求。你应该实现FindFiles或者FindFilesWithPattern(其中一个,译者注)。对于每一个目录入口(entry),文件系统程序都应该调用FillFindData函数(作为一个函数参数供 FindFiles, FindFilesWithPattern调用),FillFindData会使用包含目录信息的WIN32_FIND_DATAW结构:
FillFindData( &win32FindDataw, DokanFileInfo )。
处理通配符模式(wildcard patterns)是文件系统的责任,因为Windows命令终端(shells)不能够很好地处理模式匹配。当文件系统程序提供FindFiles,通配符模式将会通过Dokan库来自动的处理。你可以通过实现FindFilesWithPattern函数来控制通配符匹配的过程。Dokan库(dokan.dll)提供的DokanIsNameInExpression函数接口可以用来处理通配符匹配。
挂载
====================================================================
#define DOKAN_OPTION_DEBUG 1 // 输出调试信息
#define DOKAN_OPTION_STDERR 2 // 输出调试信息到标准错误输出
#define DOKAN_OPTION_ALT_STREAM 4 // use alternate stream
#define DOKAN_OPTION_KEEP_ALIVE 8 // 使用自动卸载
#define DOKAN_OPTION_NETWORK 16 // 使用网络驱动
//你需要安装Dokan网络提供器(provider)
#define DOKAN_OPTION_REMOVABLE 32 // 使用可移除驱动
typedef struct _DOKAN_OPTIONS {
USHORT Version; // 支持的Dokan版本, 比如. "530" (Dokan ver 0.5.3)
ULONG ThreadCount; // 使用的线程数
ULONG Options; // combination of DOKAN_OPTIONS_*
ULONG64 GlobalContext; // FileSystem 可以使用这个
LPCWSTR MountPoint; // 挂载点 "M:\" (驱动字符) 或者
// "C:\mount\dokan" (NTFS中的路径名)
} DOKAN_OPTIONS, *PDOKAN_OPTIONS;
int DOKANAPI DokanMain(
PDOKAN_OPTIONS DokanOptions,
PDOKAN_OPERATIONS DokanOperations);
如上所述,文件系统可以通过DokanMain函数挂载。函数一直阻塞(block)直到文件系统卸载。再把这些参数传递给DokanMain 函数之前,文件系统程序应该为Dokan运行库填写满DokanOptions中的选项,为文件系统操作填写满DokanOperations中的函数指针(比如CreateFile, ReadFile, CloseHandle, ...)。DokanOperations结构中的函数需要保证线程安全,因为他们都被执行不同上下文(contexts)的多线程调用(不是调用DokanMain的线程)。
Dokan选项如下:
版本:Dokan库的版本号。你需要一个支持的版本。Dokan库可能因为版本号的不同改变一些行为(behavior)。比如ie.530(Dokan 0.5.3)
线程数:Dokan库内部的线程数。如果这个值设定为0,那么将使用默认的值。当我们调试文件系统的时候,文件系统程序应该设定为1来避免多线程的并发冲突。
选项:DOKAN_OPTION_*常量的结合。
全局域:你的文件系统可以使用这个变量来存放一个挂载特定的结构。
挂载点:一个挂载点挂载点 "M:\" (驱动字符) 或者 "C:\mount\dokan" (需要是空的)NTFS中的路径名。
如果挂载成功,那么返回值是DOKAN_SUCCESS,否则返回值如下。
#define DOKAN_SUCCESS 0
#define DOKAN_ERROR -1 /* 普通错误 */
#define DOKAN_DRIVE_LETTER_ERROR -2 /* 坏的驱动字符 */
#define DOKAN_DRIVER_INSTALL_ERROR -3 /* 不能安装驱动 */
#define DOKAN_START_ERROR -4 /* 驱动出了某个问题 */
#define DOKAN_MOUNT_ERROR -5 /* 不能分配驱动字符或者挂载点 */
#define DOKAN_MOUNT_POINT_ERROR -6 /* 挂载点无效 */
卸载
=======================================================================
文件系统可以通过调用DokanUnmount函数来卸载。大部分情况下,程序或者shell使用文件系统挂起,卸载操作来解决问题。因为当文件系统卸载的时候,我们可以把系统恢复到原来的状态。
用户可能使用DokanCtl来卸载文件系统:
> dokanctl.exe /u DriveLetter
杂项:
======================================================================
如果在Dokan库或者使用库的文件系统程序中有bug,那么你的Windows系统将会蓝屏。因此,我们强烈建议你使用虚拟机来开发文件系统应用程序。
Dokan官方说明文档的更多相关文章
- SWFUpload 2.5.0版 官方说明文档 中文翻译版
原文地址:http://www.cnblogs.com/youring2/archive/2012/07/13/2590010.html#setFileUploadLimit SWFUpload v2 ...
- SpringMVC的API和Spring的官方说明文档的地址。
SpringMVC的API和Spring的官方说明文档的地址. 1.SpringMVC的API的URL: http://docs.spring.io/spring/docs/current/javad ...
- 【转】SWFUpload 官方说明文档(2.5.0版)
原文出自:http://www.runoob.com/w3cnote/swfupload-document.html SWFUpload使用指南请查阅:http://www.w3cschool.cc/ ...
- locust===官方说明文档,关于tasks
安装: >>> pip install locust locust在官方simple_code中如下: from locust import HttpLocust, TaskSet ...
- ICE中间件说明文档
ICE中间件说明文档 1 ICE中间件简介 2 平台核心功能 2.1 接口描述语言(Slice) 2.2 ICE运行时 2.2.1 ...
- BasicExcel说明文档
BasicExcel说明文档 BasicExcel原始链接:http://www.codeproject.com/Articles/13852/BasicExcel-A-Class-to-Read-a ...
- 为ASP.NET WEB API生成人性化说明文档
一.为什么要生成说明文档 我们大家都知道,自己写的API要供他人调用,就需要用文字的方式将调用方法和注意事项等写成一个文档以更好的展示我们设计时的想法和思路,便于调用者更加高效的使用我们的API. 当 ...
- 【腾讯GAD暑期训练营游戏程序班】游戏场景管理作业说明文档
场景管理作业说明文档 用了八叉树的算法,测出三层时最快,区域范围内物体数量为21块,控制台打印出的结果如图所示: 场景物体:游戏中,所有具有空 ...
- 浏览器内核控制Meta标签说明文档
浏览器内核控制Meta标签说明文档 原文链接 背景介绍 由于众所周知的情况,国内的主流浏览器都是双核浏览器:基于Webkit内核用于常用网站的高速浏览.基于IE的内核用于兼容网银.旧版网站.以360的 ...
随机推荐
- Pos终端中的主密钥、工作密钥、pin密钥、mac密钥
下面介绍一下加密机中最主要的几种密钥: 1.加密机主密钥(MK) 加密机主密钥(Master Key - MK)是存入在HSM机内的由三个成分合成的一对最上层密钥.在HSM机器以外的地方不会以明文形式 ...
- HDU 1272 小希的迷宫(乱搞||并查集)
小希的迷宫 Problem Description 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有 ...
- C# asp.net PhoneGap html5
很久没写博客,今天自己写一篇吧.来谈一谈c# PhoneGap,html5 与asp.net.能搜到这篇博客就说明你是一位.net开发者,即将或者正在从事移动开发. 大家可能都有疑,我是一名.net开 ...
- 利用DataSet更改数据,将更改保存到数据库中
RowState 是 DataRow 很重要的一个属性, 表示 DataRow 当前的状态. RowState 有 Added, Modified, Unchanged, Deleted, Detac ...
- 中文版的jqGrid实例大全
中文版的jqGrid实例大全 http://blog.mn886.net/jqGrid/
- 解决vs2013下创建的python文件,到其他平台(如linux)下中文乱码(或运行时报SyntaxError: (unicode error) 'utf-8' codec can't decode byte...)
Vs2013中创建python文件,在文件中没输入中文时,编码为utf-8的,如图 接着,在里面输入几行中文后,再次用notepad++查看其编码如下,在vs下运行也报错(用cmd运行就不会): 根据 ...
- ubuntu_虚拟机和SD卡链接失败,可能的原因
这个问题很简单吧,但是自己解决却用了很长时间,说一下方法吧! 1.有的虚拟机不兼容USB3.0的接口,所以在接SD卡(读卡器)时,请将读卡器拔出,插入笔记本USB2.0的接口上(当时自己没注意到这点, ...
- c++中string类型可以直接进行比较
以下代码在Ubuntu14.10下实现 /*------------------------- filename is demo.cpp --------------------------*/ #i ...
- 敏捷开发(五)- 框架SCRUM内容
本文主要是为了检测你对SCRUM的了解和使用程度,通过本文你可以检测一下 1.你们的SCRUM项目中各个角色是否合格, 2.SCRUM上面需要的会议是否有遗留,会议过程是否正确 3 ...
- XTU 1252 Defense Tower
$2016$长城信息杯中国大学生程序设计竞赛中南邀请赛$J$题 贪心. 优先删除$power$大的点. #pragma comment(linker, "/STACK:1024000000, ...