Windows 投影文件系统只读?
Windows Projected File System read only?
我尝试使用 Projected File System 来实现用户模式 ram 驱动器(之前我使用过 Dokan)。我有两个问题:
这是只读投影吗?从记事本打开文件并写入时,我找不到任何发送给我的通知。
当我使用 PrjWriteFileData() 时,文件实际上是在磁盘上创建的吗?据我了解,是的。
在那种情况下,如果没有写入投影文件,那么用这个库可以做什么有用的事情?在我看来,唯一有用的事情是最初从其他地方(比如远程仓库)创建一个目录树,但除此之外别无他法。 Dokan 似乎仍然可行。
简答:
- 它不是 read-only但是你不能直接写你的文件 通过投影到 "source" 文件系统。
WriteFileData
方法用于在 "scratch"(预计)文件系统上填充占位符文件,因此,它不会影响 "source" 文件系统。
长答案:
如@zett42 的评论所述,ProjFS 主要设计为远程 git 文件系统。因此,任何文件版本控制系统的主要目标都是处理文件的多个版本。由此产生了一个问题——我们是否需要在写入 ProjFS 文件时覆盖远程存储库中的文件?这将是灾难性的。使用 git 时,您总是在本地写入文件,并且在将更改推送到远程存储库之前它们不会同步。
当您枚举文件时,没有任何内容被写入本地文件系统。来自 ProjFS 文档:
When a provider first creates a virtualization root it is empty on the
local system. That is, none of the items in the backing data store
have yet been cached to disk.
只有在文件打开后,ProjFS 才会在本地文件系统中为它创建一个 "placeholder" - 我假设它是一个具有特殊结构的文件(不是真实的)。
As files and directories under the virtualization root are opened, the
provider creates placeholders on disk, and as files are read the
placeholders are hydrated with contents.
"hydrated"是什么意思?最有可能的是,它代表了一种特殊的数据结构,其中部分填充了真实数据。我会将占位符想象成部分填充数据的海绵。
As items are opened, ProjFS requests information from the provider to allow placeholders for those items to be created in the local file system. As item contents are accessed, ProjFS requests those contents from the provider. The result is that from the user's perspective, virtualized files and directories appear similar to normal files and directories that already reside on the local file system.
仅在更新(修改)文件后。它不再是占位符 - 它变成 "Full file/directory":
For files: The file's content (primary data stream) has been modified.
The file is no longer a cache of its state in the provider's store.
Files that have been created on the local file system (i.e. that do
not exist in the provider's store at all) are also considered to be
full files.
For directories: Directories that have been created on the local file
system (i.e. that do not exist in the provider's store at all) are
considered to be full directories. A directory that was created on
disk as a placeholder never becomes a full directory.
表示第一次写入时占位符被本地文件系统中的真实文件替换。但是如何使 "remote" 文件与修改后的文件保持同步呢? (1)
When the provider calls PrjWritePlaceholderInfo to write the
placeholder information, it supplies the ContentID in the VersionInfo
member of the placeholderInfo argument. The provider should then
record that a placeholder for that file or directory was created in
this view.
注意“提供商随后应记录该文件的占位符”。这意味着为了稍后将文件与 正确的 视图表示同步,我们必须记住修改后的文件与哪个版本相关联。假设我们在 git 存储库中,我们更改了分支。在这种情况下,我们可能会在不同的分支中多次更新一个文件。现在,提供商为什么以及何时调用 PrjWritePlaceholderInfo
?
... These placeholders represent the state of the backing store at the
time they were created. These cached items, combined with the items
projected by the provider in enumerations, constitute the client's
"view" of the backing store. From time to time the provider may wish
to update the client's view, whether because of changes in the backing
store, or because of explicit action taken by the user to change their
view.
再次想象一下在 git 存储库中切换分支;如果另一个分支中的文件不同,则必须更新文件。继续回答问题(1)。假设您想从特定分支创建 "push"。首先,您必须知道修改了哪些文件。如果您在修改文件时没有记录占位符信息,您将无法正确执行此操作(至少对于 git 存储库示例)。
还记得,占位符在修改时被真实文件替换了吗? ProjFS 有 OnNotifyFileHandleClosedFileModifiedOrDeleted
事件。这是回调的签名:
public void NotifyFileHandleClosedFileModifiedOrDeletedCallback(
string relativePath,
bool isDirectory,
bool isFileModified,
bool isFileDeleted,
uint triggeringProcessId,
string triggeringProcessImageFileName)
为了我们的理解,这里对我们来说最重要的参数是relativePath
。它将包含 "scratch" 文件系统(预计)内修改文件的名称。在这里你也知道文件是一个真正的文件(不是占位符)并且它被写入磁盘(就是这样你将无法拦截调用 before 文件被写入).现在您可以将其复制到所需位置(或稍后复制)- 这取决于您的目标。
回答问题 #2,似乎 PrjWriteFileData
仅用于填充 "scratch" 文件系统,您不能将其用于更新 "source" 文件系统。
应用程序:
至于应用程序,您仍然可以实现远程文件系统(而不是使用 Dokan),但所有写入都将缓存在本地,而不是直接写入远程位置。几个用例想法:
- 分布式文件系统
- 在线驱动客户端
- 文件系统"Dispatcher"(例如,您可以根据特定条件将文件写入不同的文件夹)
- 文件版本控制系统(例如,您可以在修改后保留同一文件的不同版本)
- 将应用程序中的数据镜像到文件系统(例如,您可以 "project" 一个带有文件夹、sub-folders 和文件缩进的文本文件)
P.S.: 我不知道有任何未记录的 API,但从我的角度来看(根据文档)我们不能将 ProjFS 用于 ramdisk 之类的目的或将文件直接写入 "source" 文件系统而不先将它们写入 "local" 文件系统。
我尝试使用 Projected File System 来实现用户模式 ram 驱动器(之前我使用过 Dokan)。我有两个问题:
这是只读投影吗?从记事本打开文件并写入时,我找不到任何发送给我的通知。
当我使用 PrjWriteFileData() 时,文件实际上是在磁盘上创建的吗?据我了解,是的。
在那种情况下,如果没有写入投影文件,那么用这个库可以做什么有用的事情?在我看来,唯一有用的事情是最初从其他地方(比如远程仓库)创建一个目录树,但除此之外别无他法。 Dokan 似乎仍然可行。
简答:
- 它不是 read-only但是你不能直接写你的文件 通过投影到 "source" 文件系统。
WriteFileData
方法用于在 "scratch"(预计)文件系统上填充占位符文件,因此,它不会影响 "source" 文件系统。
长答案:
如@zett42 的评论所述,ProjFS 主要设计为远程 git 文件系统。因此,任何文件版本控制系统的主要目标都是处理文件的多个版本。由此产生了一个问题——我们是否需要在写入 ProjFS 文件时覆盖远程存储库中的文件?这将是灾难性的。使用 git 时,您总是在本地写入文件,并且在将更改推送到远程存储库之前它们不会同步。
当您枚举文件时,没有任何内容被写入本地文件系统。来自 ProjFS 文档:
When a provider first creates a virtualization root it is empty on the local system. That is, none of the items in the backing data store have yet been cached to disk.
只有在文件打开后,ProjFS 才会在本地文件系统中为它创建一个 "placeholder" - 我假设它是一个具有特殊结构的文件(不是真实的)。
As files and directories under the virtualization root are opened, the provider creates placeholders on disk, and as files are read the placeholders are hydrated with contents.
"hydrated"是什么意思?最有可能的是,它代表了一种特殊的数据结构,其中部分填充了真实数据。我会将占位符想象成部分填充数据的海绵。
As items are opened, ProjFS requests information from the provider to allow placeholders for those items to be created in the local file system. As item contents are accessed, ProjFS requests those contents from the provider. The result is that from the user's perspective, virtualized files and directories appear similar to normal files and directories that already reside on the local file system.
仅在更新(修改)文件后。它不再是占位符 - 它变成 "Full file/directory":
For files: The file's content (primary data stream) has been modified. The file is no longer a cache of its state in the provider's store. Files that have been created on the local file system (i.e. that do not exist in the provider's store at all) are also considered to be full files.
For directories: Directories that have been created on the local file system (i.e. that do not exist in the provider's store at all) are considered to be full directories. A directory that was created on disk as a placeholder never becomes a full directory.
表示第一次写入时占位符被本地文件系统中的真实文件替换。但是如何使 "remote" 文件与修改后的文件保持同步呢? (1)
When the provider calls PrjWritePlaceholderInfo to write the placeholder information, it supplies the ContentID in the VersionInfo member of the placeholderInfo argument. The provider should then record that a placeholder for that file or directory was created in this view.
注意“提供商随后应记录该文件的占位符”。这意味着为了稍后将文件与 正确的 视图表示同步,我们必须记住修改后的文件与哪个版本相关联。假设我们在 git 存储库中,我们更改了分支。在这种情况下,我们可能会在不同的分支中多次更新一个文件。现在,提供商为什么以及何时调用 PrjWritePlaceholderInfo
?
... These placeholders represent the state of the backing store at the time they were created. These cached items, combined with the items projected by the provider in enumerations, constitute the client's "view" of the backing store. From time to time the provider may wish to update the client's view, whether because of changes in the backing store, or because of explicit action taken by the user to change their view.
再次想象一下在 git 存储库中切换分支;如果另一个分支中的文件不同,则必须更新文件。继续回答问题(1)。假设您想从特定分支创建 "push"。首先,您必须知道修改了哪些文件。如果您在修改文件时没有记录占位符信息,您将无法正确执行此操作(至少对于 git 存储库示例)。
还记得,占位符在修改时被真实文件替换了吗? ProjFS 有 OnNotifyFileHandleClosedFileModifiedOrDeleted
事件。这是回调的签名:
public void NotifyFileHandleClosedFileModifiedOrDeletedCallback(
string relativePath,
bool isDirectory,
bool isFileModified,
bool isFileDeleted,
uint triggeringProcessId,
string triggeringProcessImageFileName)
为了我们的理解,这里对我们来说最重要的参数是relativePath
。它将包含 "scratch" 文件系统(预计)内修改文件的名称。在这里你也知道文件是一个真正的文件(不是占位符)并且它被写入磁盘(就是这样你将无法拦截调用 before 文件被写入).现在您可以将其复制到所需位置(或稍后复制)- 这取决于您的目标。
回答问题 #2,似乎 PrjWriteFileData
仅用于填充 "scratch" 文件系统,您不能将其用于更新 "source" 文件系统。
应用程序:
至于应用程序,您仍然可以实现远程文件系统(而不是使用 Dokan),但所有写入都将缓存在本地,而不是直接写入远程位置。几个用例想法:
- 分布式文件系统
- 在线驱动客户端
- 文件系统"Dispatcher"(例如,您可以根据特定条件将文件写入不同的文件夹)
- 文件版本控制系统(例如,您可以在修改后保留同一文件的不同版本)
- 将应用程序中的数据镜像到文件系统(例如,您可以 "project" 一个带有文件夹、sub-folders 和文件缩进的文本文件)
P.S.: 我不知道有任何未记录的 API,但从我的角度来看(根据文档)我们不能将 ProjFS 用于 ramdisk 之类的目的或将文件直接写入 "source" 文件系统而不先将它们写入 "local" 文件系统。