• 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 program (dokanctl.exe) MIT    
    - mount service (mouter.exe)     MIT    
    - samples (mirror.c)             MIT

    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 一致,但必须做到线程安全,因为有可能有多个线程调用。

    这些函数有个典型的调用顺序:   
    1. CreateFile(OpenDirectory, CreateFile)    
    2. Other functions    
    3. Cleanup    
    4. CloseFile

    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_OPTIONS    DokanOptions,

    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:mountdokan" (path in NTFS)

    } DOKAN_OPTIONS, *PDOKAN_OPTIONS;

      5.      卸载 

    调用 DokanUnmount进行文件系统的卸载。用户也可以使用 DokanCtl 像这样进行卸载:

    > dokanctl.exe /u DriveLetter

     
     
  • 相关阅读:
    Activity的几种启动模式
    android 环境搭建
    认识python中__name__、程序主入口
    32位与64位之谈
    shell中字符串基本用法
    C++ push方法与push_back方法
    8-10总结
    第九章 硬件抽象层:HAL
    第十章 嵌入式Linux的调试技术
    第八章
  • 原文地址:https://www.cnblogs.com/langren1992/p/5149422.html
Copyright © 2020-2023  润新知