即在存储设备上组织文件的方法。
*** 作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统。
文件系统由三部分组成:文件系统的接口,对对象 *** 纵和管理的软件集合,对象及属性。
从系统角度来看,文件系统是对文件存储设备的空间进行组织和分配,负责文件存储并对存入的文件进行保护和检索的系统。
1.Dokan Library 简介
Dokan Library 帮助程序员在windows系统下轻松建立用户级文件系统,不需要写设备驱动,其与FUSE(Linux user mode file system)类似。
2.Dokan原理
Dokan Library包含以下部分:
dokan.sys是内核态文件系统驱动,当此驱动安装之后,就可以创建自己的文件系统了。而我们创建文件系统(实现Dokan库的API)的程序称为文件系统程序。这时,程序提出的文件 *** 作请求(例如CreateFile, ReadFile, WriteFile)就会送到Windows I/O subsystem (内核中运行),后者会继续将请求送到dokan.sys。文件系统程序可以利用dokan.dll提供的函数将我们的回调函数( *** 作实现函数)注册到dokan.sys中,后者会在收到请求之后调用这些我们提供的函数。回调函数的结果会送回提出请求的程序。(可参见图一)
dokan.sys 相当于一个运行在内核态的代理,作为提出请求的程序和我们实现各种 *** 作的文件系统程序的桥梁。至此,我们程序员就可以在用户态轻松的创建调试文件系统程序,大大提高了开发效率。
3.创建文件系统
与FUSE类似,我们的文件系统程序需要实现一个结构体中的各个 *** 作DOKAN_OPERATIONS(声明在dokan.h中),然后该结构体作为参数调用DokanMain挂载文件系统。这些函数的参数与Windows APIs 一致,但必须做到线程安全,因为有可能有多个线程调用。
这些函数有个典型的调用顺序:
file creation functions (OpenDirectory, CreateFile,…)总是在file access operations (listing directory, reading file attributes, …)之前调用。当文件被CloseFile Windows API关闭时,Cleanup程序总是被dokan.sys调用。
返回值为0时表示 *** 作成功。
每个函数的最后一个参数是DOKAN_FILE_INFO structure
typedef struct _DOKAN_FILE_INFO {
ULONG64 Context//文件系统程序维护,可作为文件句柄
ULONG64 DokanContext //Dokan Library维护
ULONG ProcessId // *** 作ID
BOOL IsDirectory //目录= TRUE
}DOKAN_FILE_INFO, *PDOKAN_FILE_INFO
每一个文件句柄都与一个DOKAN_FILE_INFO struct对应。该结构创建在文件被CreateFile系统调用打开时,回收在文件被CloseFile系统调用关闭时。
下面是几个 *** 作的声明:
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
//CloseHandle ( Windows API)执行之后调用,如果文件句柄在//CreateFile中创建,应该在此释放,而不是在CloseFile。
//如果用户在内存中缓存了文件,调用Cleanup之后还有可能调用读写// *** 作。
int (*Cleanup) (
LPCWSTR, // FileName
PDOKAN_FILE_INFO)
//如果用户调用CloseHandle后再打开相同文件,CreateFile之前可能//不会再调用CloseFile,这可能会出共享错误。
int ( CloseFile) (
LPCWSTR, // FileName
PDOKAN_FILE_INFO)
int ( FindFiles) (
LPCWSTR, // PathName
PFillFindData, // call this function with PWIN32_FIND_DATAW
PDOKAN_FILE_INFO)// (see PFillFindData definition)
// You should implement either FindFires or FindFilesWithPattern
int (*FindFilesWithPattern) (
LPCWSTR, // PathName
LPCWSTR, // SearchPattern
PFillFindData, // call this function with PWIN32_FIND_DATAW
PDOKAN_FILE_INFO)
上面两个函数是回应列目录项 *** 作请求的。对每一个目录项,文件系统程序都会调用函数FillFindData( &win32FindDataw, DokanFileInfo )。由于Windows的shell对于模式匹配不支持,文件系统程序就要执行通配模式。当文件系统程序实现FindFiles,DokanLibrary会自动添加通配模式,我们也可以自己实现FindFilesWithPattern来加以控制。DokanIsNameInExpression (dokan.dll)函数就是用来实现模式匹配的。
4.挂载
前面已经提到,可以调用DokanMain函数来挂载文件系统。该程序会阻塞到文件系统被卸载。
我们的文件系统要做两件事,一是为Dokan运行库填写DokanOptions,二是填写带各个 *** 作函数指针的DokanOperations作为DokanMain的参数。
int DOKANAPI DokanMain(
PDOKAN_OPTIONSDokanOptions,
PDOKAN_OPERATIONS DokanOperations)
typedef struct DOKAN_OPTIONS {
USHORT Version // Supported Dokan Version, ex. "530" (Dokan ver 0.5.3)
ULONG ThreadCount // number of threads to be used
ULONG Options // combination of DOKAN_OPTIONS *
ULONG64 GlobalContext // FileSystem can use this variable
LPCWSTR MountPoint// mount point "M:" (drive letter) or
// "C:\mount\dokan" (path in NTFS)
} DOKAN_OPTIONS, *PDOKAN_OPTIONS
5.卸载
调用 DokanUnmount进行文件系统的卸载。用户也可以使用 DokanCtl 像这样进行卸载:
Dokan创建之初的目的和FUSE(Filesystem in Userspace)一样,即为了实现用户自己的文件系统。开发者通过dokan开发文件系统,实现的是一个应用程序而不是复杂的内核驱动。(Windows内核驱动开发也不见得比Linux简单。)Dokan就是Windows上的FUSE。而目前Dokan已经支持Fuse,意味着Linux Fuse程序也可以实现向Windows平台的迁移。 目前Dokan已经被替换成Dokany(自0.6.0版本),广泛支持32位或64位X86和ARM架构。支持的Windows版本有 - Windows Server 2019/2016/2012 R2/2012/2008 R2 SP1 - Windows 10/8.1/8/7 SP1 简而言之,和FUSE如出一辙。 Dokan库包含用户态的动态链接库(dokan.dll)和内核态的驱动程序(dokan1.sys)。( 可以类比FUSE提供用户态的动态链接库libfuse.so和内核态驱动fuse.ko。) 使用dokan库创建的文件系统视为 文件系统程序 。 文件 *** 作比如创建文件CreateFile、读文件ReadFile和写文件WriteFile的请求将会发送给内核态子系统,然后转递给驱动程序。 文件系统程序 通过用户态提供的函数接口,在驱动程序中注册回调接口。驱动程序到信息后会调用这些回调函数,最后这些请求在用户态的文件系统程序中被处理。Dokan扮演的是应用程序和 文件系统程序 直接的代理角色。 第一步实现DOKAN_OPERATIONS结构体里的函数。这些函数会被注册成回调函数。DOKAN_OPERATIONS会在主函数DokanMain中作为参数传递使用。 一般 *** 作文件的顺序是 - DOKAN_OPERATIONS::ZwCreateFile - 其他 *** 作,比如写、读等 - DOKAN_OPERATIONS::CleanUp - DOKAN_OPERATIONS::CloseFile 即创建、实际 *** 作、清理和关闭。清理主要是清理请求和关闭文件句柄,而关闭是清理尚存的上下文结构。 每个 *** 作成功返回STATUS_SUCCESS,如果失败则返回不同的错误状态NTSTATUS。另外,每一个Dokan *** 作都要带一个结构体DOKAN_FILE_INFO。每个文件句柄会关联该结构。该结构的主要目的是保存当前 *** 作的文件信息,比如上下文 *** 作信息、是否为目录类型、是否读缓存、同步 *** 作等定义 *** 作行为的信息。具体详见附录中地址。 实现了 线程安全 的文件系统 *** 作,调用DokanMain函数即可挂载文件系统到Windows中,该函数会在卸载之前保持阻塞状态。 源码包里面提供了Mirror,可以作为案例入门Dokan的开发。 Dokan Fuse在使用时需要链接 dokanfuse.dll 的动态库。 另外由于Linux和Windows在处理删除和重命名上的不同会导致一些移植出现问题 (Linux允许打开的文件被删除,而Windows则不允许)。项目地址:https://github.com/dokan-dev/dokany 结构体DOKAN_FILE_INFO描述:https://dokan-dev.github.io/dokany-doc/html/struct_d_o_k_a_n___f_i_l_e___i_n_f_o.html欢迎分享,转载请注明来源:内存溢出
评论列表(0条)