本文是系列「Windows I/O 的深层」的最终回。
自从第 1 回设备栈图中画出「文件系统过滤器(杀毒软件・加密・Procmon 等)」这个方框以来,本系列中夹在中间的角色已经数次登场:Procmon 能够记录全部 I/O 的理由(第 1 回)。「唯独那个环境的文件访问很慢」(第 2 回)。文件一打开 OneDrive 就开始下载的重解析点(第 5 回)。这一回终于要正面处理这套介入机制本身──文件系统过滤器驱动程序与迷你过滤器──把系列中埋下的所有伏笔悉数回收。
1. 先说结论
- 「介入 I/O」是操作系统官方认可的扩展点。文件系统过滤器可以查看、改写、拒绝对文件系统的请求,甚至代为处理(第 2 章)。1
- 当前的标准是迷你过滤器。为解决直接介入设备栈的传统方式所存在的问题(顺序不确定・无法卸载),已经完成了向 Windows 自带的过滤器管理器(FltMgr)注册回调的方式的世代更替(第 2 章)。23
- 运作方式是 pre/post 回调。各操作的前后会按照注册顺序=高度顺序依次被调用。放行・完成・拒绝・改写──第 1 回中看到的「驱动程序的选项」在这里原封不动地适用(第 3 章)。2
- 高度(海拔)决定顺序。按用途划分的组分别被分配了编号区间(Activity Monitor 为 360000-389999,Anti-Virus 为 320000-329999 等),挂接到卷上的每个实例都拥有唯一编号(第 4 章)。45
- 你电脑中的住户可以用
fltmc查看。Procmon(仅限运行期间)、杀毒软件、OneDrive 的云文件过滤器──全都会列在这里(第 5 章)。 - 杀毒软件的排除设置,其实质是「省略该产品自身的扫描」,不会影响其他迷你过滤器。排除是以削弱保护为代价的权衡取舍,对开发用卷而言,还有 Dev Drive(异步扫描)这一更安全的选项(第 6 章)。67
- 「唯独那个环境很慢」的排查,要从 Procmon 的 Duration 列与
fltmc的构成比较入手(第 7 章)。
2. 介入者们的历史 ── 从传统过滤器到 FltMgr
文件系统过滤器驱动程序是能够拦截发往文件系统(或其下层卷)的请求的驱动程序。它可以记录请求、监视请求、修改内容,甚至可以拒绝或代为处理──是杀毒软件、加密、备份、分层存储等软件的基石。1
旧的实现方式(传统过滤器)是在第 1 回见过的设备栈上,直接叠加自己的设备对象。作为机制来说很直观,但在实务中问题一大堆──叠加的顺序依赖于加载顺序,难以得到保证;一旦叠上去就无法安全地退出(不能卸载);还容易成为过滤器之间相性问题(bug)的温床。
于是 Windows 引入了过滤器管理器(FltMgr)。FltMgr 自身作为操作系统自带的过滤器立于栈中,各个过滤器功能则以迷你过滤器的身份向 FltMgr 注册回调。2
flowchart TB
subgraph OLD["传统方式"]
L1["传统过滤器 A"]
L2["传统过滤器 B"]
LFS1["文件系统"]
L1 --> L2
L2 --> LFS1
NOTE1["顺序由加载顺序决定<br/>无法安全卸载"]
end
subgraph NEW["迷你过滤器方式,当前标准"]
FM["过滤器管理器,FltMgr<br/>操作系统自带,栈中只有它一个"]
M1["迷你过滤器 A,高度较高"]
M2["迷你过滤器 B,高度较低"]
LFS2["文件系统"]
FM -. "注册回调" .- M1
FM -. "注册回调" .- M2
FM --> LFS2
NOTE2["顺序由高度确定性地决定<br/>可在任意时刻加载<br/>支持的过滤器还可以卸载"]
end
图 1:世代更替。不再「叠加」在栈上,而是向 FltMgr「注册」
迷你过滤器方式的优点是官方明确列出的──可以在任意时刻加载,能够控制顺序,实现了卸载回调的过滤器还能在运行期间卸载(未实现或拒绝卸载的过滤器则无法移除)。3 为了与传统过滤器共存,FltMgr 可以作为多个「帧」立于栈中的多个位置,而迷你过滤器即使被卸载后重新加载,也能保证回到同一个位置(同一个高度)。2 现代的杀毒软件・监控・同步软件,几乎全部都是这种迷你过滤器。
3. 迷你过滤器的运作方式 ── pre/post 回调
迷你过滤器会向 FltMgr 声明自己「对哪些操作感兴趣」。比如只对 IRP_MJ_CREATE(打开)和 IRP_MJ_WRITE(写入)感兴趣。这样一来,每当这些操作流经时,操作之前(pre 回调)和操作之后(post 回调)就会被调用。
sequenceDiagram
participant IOM as I/O 管理器
participant FM as FltMgr
participant A as 迷你过滤器 A<br/>(高度较高)
participant B as 迷你过滤器 B<br/>(高度较低)
participant FS as NTFS
IOM->>FM: 请求(IRP_MJ_CREATE 等,第 1 回的世界)
FM->>A: pre 回调
FM->>B: pre 回调
FM->>FS: 传给文件系统
FS-->>FM: 处理结果
FM-->>B: post 回调
FM-->>A: post 回调
FM-->>IOM: 完成(回到第 1 回的完成流程)
图 2:pre/post 回调。去程按高度从高到低调用,回程则按相反顺序
各个回调能做什么?与第 1 回第 4.3 节「驱动程序的三个选项」相同的构图,在这里以更安全的 API 形式被提供出来。
flowchart TB
PRE["pre 回调被调用"]
Q{"该如何处理这次操作"}
PASS["放行<br/>不需要 post 时也一并声明"]
DENY["拒绝<br/>立即返回访问拒绝等结果<br/>例如——检测到病毒、禁止写入"]
DONE["自行完成<br/>例如——云文件过滤器<br/>取得实体后代为交出"]
MOD["修改参数或内容后放行<br/>例如——加密过滤器"]
PRE --> Q
Q --> PASS
Q --> DENY
Q --> DONE
Q --> MOD
图 3:pre 回调的选项。「查看・拦下・代为处理・改写」全部都是官方支持的做法
至此,第 4 回留下的悬念也在这里得到回收──迷你过滤器同样能够列席快速 I/O(不生成 IRP 的捷径)。这是因为 FltMgr 把回调机制也贯穿到了快速 I/O 路径上,不会像传统过滤器时代那样「一旦被抄了近道就看不见」。Procmon 日志中连 FASTIO_ 开头的行都能一并列出,正是拜这个位置所赐。
4. 高度 ── 「标高」决定顺序
当多个过滤器对同一个操作都感兴趣时,谁先看到就是个重大的问题。杀毒软件如果不比加密过滤器先看到,就会沦为对密文进行扫描;监控工具如果不站在所有人之上,就无法观察到全貌。
决定这个顺序的是高度(altitude)。按过滤器的种类各自定义了加载顺序组与编号区间。准确地说,被赋予高度的单位并非驱动程序整体,而是挂接到卷上的迷你过滤器「实例」。编号具有唯一性,数字越大,位置越靠近栈的上层(越靠近应用侧)。4 一个驱动程序可以拥有多个实例定义,并以不同的高度出现在多处,这也是 fltmc instances 的清单以实例为单位列出的原因。
flowchart TB
APP["应用侧,数字较大"]
G1["FSFilter Activity Monitor,360000-389999<br/>观察与记录 I/O,Procmon 位于此处"]
G2["FSFilter Undelete,340000-349999<br/>已删除文件的恢复"]
G3["FSFilter Anti-Virus,320000-329999<br/>病毒的检测与清除"]
G4["FSFilter Replication,300000-309999<br/>向远程复制"]
G5["FSFilter Continuous Backup,280000-289999<br/>持续备份"]
G6["再往下,还有 Content Screener、<br/>Quota Management、System Recovery、<br/>加密与压缩等区间依次排列"]
FS["文件系统侧,数字较小"]
APP --> G1 --> G2 --> G3 --> G4 --> G5 --> G6 --> FS
图 4:高度区间(节选)。每种用途都有各自应处的「海拔」
重要的是,这些编号由 Microsoft 统一分配和管理。5 并非厂商自行认领,而是要申请后才能获得──因此无论在哪台电脑上,都能保持「监控高于杀毒软件、杀毒软件高于加密」这样的秩序。这正是对传统过滤器时代那种「加载顺序抽奖」问题给出的答案。
自行开发迷你过滤器时的申请渠道。面向开发者,这里只写下接下来的一步。高度的申请要按照 Request a Filter Altitude Identifier 中的步骤,把邮件主题设为「Filter altitude request」,用英文发送到 fsfcomm@microsoft.com 提出申请。需要填写公司名称、联系方式(不是个人邮箱,而是能够长期使用的公司别名)、产品名称、产品 URL、过滤器说明、驱动程序文件名、过滤器类型、启动类型、希望所属的加载顺序组以及希望获得的高度,所有项目都必须填写。文档中也明确写明处理大约需要 30 个工作日、没有加急受理窗口、分配到的编号有可能与希望值不同。8 另外,如果一家公司在同一个加载顺序组中已经拥有整数高度,就可以自行为该编号附加小数(例如 325000.3)来决定新值,此时事后发邮件告知即可。8
5. 住户介绍 ── 用 fltmc 查看你的电脑
道理讲到这里为止,让我们来看看实物。在具有管理员权限的命令提示符中执行:
:: 已注册的迷你过滤器一览(附高度)
fltmc
:: 哪个卷挂接了哪些过滤器
fltmc instances
:: 从卷的角度查看
fltmc volumes
不带参数的 fltmc 会输出与 fltmc filters 相同的列表。输出共 4 列,Microsoft 的文档中也刊载了相同格式的示例。9
C:\Windows\system32>fltmc
Filter Name Num Instances Altitude Frame
------------------------------ ------------- ------------ -----
bindflt 1 409800 0
cldflt 1 409500 0
WdFilter 4 328010 0
luafv 1 135000 0
FileInfo 4 45000 0
以上是用于说明的节选。排列的成员与实例数量因环境而异,但高度的数值是 Microsoft 分配的固定值,因此可以与第 4 章提到的公开列表对照核实。
列的含义如下。
| 列 | 含义 |
|---|---|
| Filter Name | 过滤器(驱动程序)的名称 |
| Num Instances | 挂接到了多少个卷上,即第 4 章所说的实例数量 |
| Altitude | 高度。数值越大越靠近应用侧 |
| Frame | FltMgr 的帧编号。如果这里显示为 <Legacy>,就说明存在不经过 FltMgr 的传统过滤器在运行。9 |
仅凭这 5 行就能看出,bindflt 与 cldflt 位于最上层的 FSFilter Top 区间(400000-409999),WdFilter 位于 Anti-Virus 区间(320000-329999),FileInfo 位于最底层的 FSFilter Bottom 区间(40000-49999)。第 4 章中「每种用途都有各自应处的海拔」这一构图,就这样直接以数字得到了验证。而且启动 Procmon 之后再执行一次 fltmc,Activity Monitor 区间(360000-389999)就会多出一行以 PROCMON 开头的记录。
虽然阵容因环境而异,但典型的住户都是本系列中的常客。
WdFilter── Microsoft Defender 的迷你过滤器。位于 Anti-Virus 区间。在许多电脑上,是所有文件 I/O 都必经的关卡。cldflt── 云文件过滤器。是 OneDrive 按需访问文件的执行部队,负责在第 5 回见过的重解析点(占位符)被打开时准备好实体内容。10PROCMON24(等) ── 只在 Process Monitor 运行期间出现的、Activity Monitor 区间的临时迷你过滤器。Procmon 能够看到全部 I/O 的谜底就在这里。11 请在启动前后分别执行fltmc加以对比。- 除此之外,还有备份软件、加密(防信息泄露)产品、EDR、虚拟化存储等──越是业务用电脑,住户往往越多。
把从第 1 回起就一直使用的 Procmon 这个工具,放到最终回中从工具箱外面重新审视一番,就会发现一个漂亮的循环──「观察者本身,也是与被观察对象同一套机制下的住户」。
6. 杀毒软件把时间花在哪里
过滤器带来的实务影响中,最大的一项就是杀毒软件的扫描成本。下面用图来说明时间究竟花在了哪里(具体细节因产品而异,以下是典型形态)。
sequenceDiagram
participant App as 应用
participant AV as AV 迷你过滤器
participant FS as NTFS
App->>AV: 打开文件
Note over AV: pre-create: 对路径与策略进行事先判定
AV->>FS: 放行(执行打开)
FS-->>AV: 打开成立(post-create)
Note over AV: 若是尚未扫描过的文件<br/>会在此处扫描内容<br/>发现问题则取消该次打开<br/>── 这是导致打开变慢的主因
AV-->>App: 若无问题则返回句柄
App->>AV: 写入与关闭
Note over AV: 发生变更的文件<br/>会在关闭等时机成为重新扫描的对象
Note over App,FS: 在大量小文件的场景下,比如构建产生的中间文件<br/>这一往返会随文件数量不断累积
图 5:扫描成本的发生位置。单个文件上的开销虽小,但数万个文件累积起来就会成为主导因素
在此基础上,就能够准确理解两个实务话题。
排除设置的技术含义。对于路径与排除列表匹配的 I/O,过滤器会省略扫描处理。过滤器本身并不会从栈中消失,实际情况是「不检查」这一判断被提前做出而已。还有另一个重要的限定──排除只对拥有该设置的产品自身的过滤器生效。Microsoft Defender 的排除设置改变的是 WdFilter 的扫描,对同时运行的其他迷你过滤器(其他厂商的杀毒软件・EDR・备份・加密等)的行为不会产生任何影响。如果遇到「明明设置了排除,速度却依然没有起色」的情况,请怀疑是否有别的住户在占用时间(参见第 7 章的 fltmc 对比)。效果虽然显著,但排除确实会削弱该处的保护。Microsoft 的文档也反复警告,排除会削减防御力,应在评估风险的基础上保持在最小范围。6 误报处理与性能影响方面的实务内容,我们在《当自研 Windows 应用被 Microsoft Defender 判定为病毒》一文中已经处理过。
Dev Drive 这一新答案。这是专为开发工作负载(大量小文件)设计的专用卷,Microsoft Defender 会以性能模式(异步扫描)运行于其上。它被定位为文件夹排除的更安全的替代方案,默认情况下不会挂接额外的过滤器,同时文档中也明确写有对「把过滤器全部拆除后运行」这种做法的强烈警告。7 这是 Microsoft 目前针对「想让构建变快,又害怕设置排除」这一诉求给出的推荐解法。
7. 「唯独那个环境很慢」的排查步骤
最后,把系列中积累起来的工具汇总成一套排查流程。
flowchart TB
S["症状,同一个应用却唯独在特定环境中<br/>文件访问缓慢"]
P1["在 Procmon 中查看 Duration 列<br/>时间消耗在哪个操作上,<br/>IRP_MJ_CREATE?还是 WRITE?"]
Q1{"特定操作是否一律偏慢?"}
F1["用 fltmc instances 与更快的环境对比<br/>查看过滤器构成的差异"]
Q2{"差异中的过滤器是原因吗?"}
A1["考虑排除设置,附带风险评估<br/>或 Dev Drive,并与厂商沟通"]
A2["怀疑过滤器以外的因素,<br/>缓存,第 4 回・碎片化或 MFT,第 5 回・<br/>网络目标 UNC・设备本身"]
S --> P1 --> Q1
Q1 -->|"是"| F1 --> Q2
Q2 -->|"是"| A1
Q2 -->|"否"| A2
Q1 -->|"否,零星发生"| A2
图 6:区分是否由过滤器导致的缓慢。关键在于「按操作统计的耗时」与「环境之间的过滤器构成差异」
要点有两个。第一,Procmon 记录着每个操作各自的耗时(Duration)。只要能把「慢」拆解成「哪个操作慢」,找出元凶的工作就已经完成了一半。第二,环境差异往往就是过滤器构成的差异。开发机与生产机、自家电脑与客户现场的电脑──只需把 fltmc 的输出并排对比,可疑的候选就会浮现出来。
从未用过 Procmon 时的最初三步。由于 Duration 列默认并不显示,为了不在这里卡住,先把具体操作写下来。
- 以管理员身份启动
Procmon.exe。 - 打开 Options 菜单 > Select Columns…,在列的清单中勾选 Duration。
- 通过 Filter 菜单 > Filter…(Ctrl+L) 输入
Process Name/is/ 目标 exe 名称 /Include,先按下 Add 按钮再点 OK(不按 Add 条件不会生效)。
在此基础上点击 Duration 列进行排序,耗时较多的操作就会汇聚到上方。如果要按进程或按文件进行汇总统计,也可以使用 Tools 菜单 > File Summary。ProcMon 的整体操作方法,我们已经汇总在《Process Monitor(ProcMon)实战指南》中。
8. 系列收尾 ── 六回的全景地图
至此,第 1 回所绘制的地图上所有的方框都已经打开。下面把全貌汇总成一张图。
flowchart TB
APP["应用程序<br/>ReadFile / WriteFile / async-await"]
API["第 2 回,同步・异步 I/O<br/>句柄的模式与 OVERLAPPED"]
IOCP["第 3 回,IOCP 与 .NET 线程池<br/>完成通知的接收与延续的执行"]
IOM["第 1 回,I/O 管理器与 IRP<br/>名称解析・三种对象・设备栈"]
FLT["第 6 回,过滤器与迷你过滤器<br/>FltMgr・高度・pre/post"]
CACHE["第 4 回,缓存管理器<br/>256KB 视图・lazy writer・快速 I/O<br/>与 NTFS 协同工作"]
NTFS["第 5 回,NTFS<br/>MFT・数据流・链接・两种日志"]
HW["存储栈与设备"]
APP --> API
API --> IOM
IOCP -. "完成会回到这里" .-> APP
IOM --> FLT
FLT --> NTFS
NTFS -. "启用缓存的 I/O 会协同处理<br/>文件系统调用缓存功能" .- CACHE
NTFS --> HW
HW -. "中断到完成,第 1 回" .-> IOCP
图 7:系列全景地图。缓存管理器并非「途经的一层」,而是与文件系统协同工作的伙伴,缓存未命中时会由 NTFS 向存储发出请求
- 第 1 回:全貌 ── 所有读写都会变成 IRP
- 第 2 回:同步/异步 ── OVERLAPPED 的真正含义
- 第 3 回:IOCP ── async/await 的地下室
- 第 4 回:缓存 ── 你的 WriteFile 究竟何时写入磁盘
- 第 5 回:NTFS ── 从 MFT 理解文件系统
- 第 6 回:过滤器与迷你过滤器(本文) ── Procmon 与病毒扫描为何能够介入 I/O
9. 总结 ── 写在系列结尾
以下是最终回的总结。
- 介入 I/O 是操作系统官方认可的扩展点,当前的标准是向 FltMgr 注册回调(迷你过滤器)。顺序由高度确定性地决定,编号由 Microsoft 统一分配和管理。245
- 运作方式是pre/post 回调。可以放行・拒绝・代为处理・改写,也能够列席快速 I/O。Procmon、Defender、OneDrive 全都是这套机制之下的住户。11110
- 排除设置=省略扫描,是与保护之间的权衡取舍。对开发用卷而言,还有 Dev Drive(异步扫描) 这一更安全的选项。67
- 「唯独那个环境很慢」,要从Procmon 的 Duration 与
fltmc的构成差异入手加以区分──系列中的工具原封不动地就成为了排查步骤。
如果要用一句话概括整个系列的结论,那就是──Windows 的 I/O,是由命名空间确定目的地、把请求封装成数据包(IRP)在各层之间流转、并让每一层都可以选择「查看・托管・代为处理」的一套一以贯之的设计。在 File.ReadAllText 这一行代码之下,这六回所讲述的结构,每一次都在切实运作。与其死记硬背 API 的行为,不如从这张地图出发推导出「理应如此」的结论──这正是希望通过本系列让各位获得的能力。感谢各位陪伴走完这段漫长的旅程。
相关文章
- Windows I/O 的深层(第1回) ── 所有读写都会变成 IRP:I/O 系统全貌
- Windows I/O 的深层(第4回) ── 缓存管理器:你的 WriteFile 何时才能到达磁盘
- Windows I/O 的深层(第5回) ── NTFS 的内部结构:从 MFT 理解文件系统
- Process Monitor(ProcMon)实战指南 —— 10 分钟定位「配置未生效」「ACCESS DENIED」问题
- 当自研 Windows 应用被 Microsoft Defender 判定为病毒 ── 误报处理与性能影响应对指南
- Process Explorer / Handle / VMMap 实战 ── 从此刻的状态追查挂起・泄漏・「文件正在使用」问题
- Windows 应用程序开发安全性最低限度检查清单
相关咨询领域
合同会社小村软件承接因过滤器驱动程序而产生的 Windows 业务应用性能问题与故障排查,例如「唯独特定环境很慢」「安全软件与自家应用互相干扰」等情形。
参考链接
-
Microsoft Learn,About file system filter drivers。关于文件系统过滤器驱动程序是一种可选的驱动程序,能够拦截发往文件系统或其他过滤器驱动程序的请求;通过拦截请求,可以在请求到达原本的目的地之前扩展或替换其功能,能够记录、监视请求,修改数据,以及阻止某些操作;杀毒工具、加密程序、分层存储管理系统等都是过滤器驱动程序的示例等内容。 ↩ ↩2 ↩3
-
Microsoft Learn,Filter Manager Concepts。关于过滤器管理器(FltMgr)是 Windows 自带的内核模式驱动程序,公开了简化迷你过滤器驱动程序开发的功能;迷你过滤器可以在 I/O 操作前后(pre/post 回调)注册处理;为了与传统过滤器共存,FltMgr 可以以帧(frame)的形式挂接到 I/O 栈的多个位置;以及迷你过滤器在卸载又重新加载后,会回到同一帧的同一高度等内容。 ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn,Advantages of the Filter Manager Model。关于迷你过滤器模型相较于传统过滤器模型所具有的优点,包括能够更好地控制过滤器的加载顺序、与传统过滤器不同,迷你过滤器可以在任意时刻加载、支持卸载,以及可以连接到 DAX 卷等内容。 ↩ ↩2
-
Microsoft Learn,Load order groups and altitudes for minifilter drivers。关于针对文件系统过滤器按用途定义了加载顺序组,并为各组分配了高度区间;所有过滤器驱动程序都拥有唯一的高度标识符,决定了其在 I/O 栈中相对于其他过滤器的位置;以及组的示例包括 FSFilter Activity Monitor(360000-389999,观察与报告 I/O)、FSFilter Undelete(340000-349999)、FSFilter Anti-Virus(320000-329999,在文件 I/O 过程中检测和清除病毒)、FSFilter Replication(300000-309999)、FSFilter Continuous Backup(280000-289999)等内容。 ↩ ↩2 ↩3
-
Microsoft Learn,Allocated altitudes。关于迷你过滤器的高度由 Microsoft 分配和管理,并维护着一份公开的已分配高度列表;该列表中 WdFilter.sys 被列为 FSFilter Anti-Virus 组的 328010,cldflt.sys 被列为 FSFilter Top 组的 409500 等内容。 ↩ ↩2 ↩3
-
Microsoft Learn,Configure and validate exclusions for Microsoft Defender Antivirus。关于 Microsoft Defender 的排除设置会使被排除的文件、文件夹与进程不再成为扫描对象;文档中反复提醒,排除会降低保护级别,应在评估必要性之后审慎定义等内容。 ↩ ↩2 ↩3
-
Microsoft Learn,Set up a Dev Drive on Windows 11。关于 Dev Drive 是专为开发工作负载设计的卷,Microsoft Defender 会以性能模式(异步扫描)在其上运行;这一设计在兼顾速度与性能的同时,被定位为文件夹排除的安全替代方案(secure alternative to folder exclusions);默认情况下不会有额外的过滤器挂接到 Dev Drive 上;以及文档警告称,拆除杀毒过滤器运行会带来严重的安全风险等内容。 ↩ ↩2 ↩3
-
Microsoft Learn,Request a Filter Altitude Identifier。关于申请新的过滤器高度需要将主题设为「Filter altitude request」的 ASCII 文本邮件发送到 fsfcomm@microsoft.com;需要填写公司名称、联系邮箱(不是个人邮箱而是可长期使用的公司别名)、产品名称、产品 URL、过滤器说明、过滤器文件名、过滤器类型、启动类型、希望所属的加载顺序组、希望获得的高度等全部项目;处理预计需要 30 个工作日,除此步骤外没有其他申请窗口;Microsoft 有可能分配与希望不同的高度;以及已经拥有整数高度的公司,可以在同一加载顺序组内自行创建附加小数的独立高度,事后告知即可等内容。 ↩ ↩2
-
Microsoft Learn,Blocking legacy file system filter drivers。关于在具有管理员权限的命令提示符中执行
fltmc filters,会以「Filter Name / Num Instances / Altitude / Frame」这 4 列列出过滤器;Frame 列显示为<Legacy>的,是不经过 FltMgr 的传统文件系统过滤器驱动程序,而迷你过滤器的 Frame 中会填入数值,如 0 等内容。 ↩ ↩2 -
Microsoft Learn,Cloud Files API。关于云文件 API(云文件过滤器)是同步引擎(如 OneDrive 的按需访问文件)的基础,能够将云端文件以占位符的形式在本地呈现,并在被访问时获取实体内容。 ↩ ↩2
-
Microsoft Learn,Process Monitor - Sysinternals。关于 Process Monitor 是一款能够实时显示文件系统、注册表以及进程/线程活动的高级监视工具(如正文所述,运行期间可以在 fltmc 的列表中观察到它以迷你过滤器的身份存在)。 ↩ ↩2
相关文章
共享相同标签的最新文章。可以围绕相近的主题进一步加深理解。
Windows I/O 的深层(第1回) ── 所有读写都会变成 IRP:I/O 系统全貌
本文是从根源讲解 Windows I/O 系统的系列第 1 回。通过图解梳理对象管理器的命名空间、驱动程序・设备・文件这三种对象、IRP 的生命周期,直至 CloseHandle 的背后机制。
Windows I/O 的深层(第5回) ── NTFS 的内部结构:从 MFT 理解文件系统
本文是通过图解讲解 NTFS 内部结构的系列第 5 回。从开发者视角整理 MFT 与文件记录、多数据流(Zone.Identifier)、硬链接与 8.3 短文件名、重解析点、两种日志,直至稀疏与压缩等内容。
Windows I/O 的深层(第4回) ── 缓存管理器:你的 WriteFile 何时才能到达磁盘
本文是图解 Windows I/O 系列的第 4 回,讲解缓存管理器:以文件映射方式实现的缓存、先读与延迟写入、FlushFileBuffers 与 FILE_FLAG_NO_BUFFERING 的使用场景划分,直至断电导致数据丢失的条件。
Windows I/O 的深层(第2回) ── 同步 I/O 与异步 I/O:OVERLAPPED 的真正含义
本文是通过图解讲解 Windows 同步 I/O 与异步 I/O(重叠 I/O)的系列第 2 回。整理 FILE_FLAG_OVERLAPPED 的含义、完成通知的四种方式、明明是异步却同步完成的条件、取消的正确做法,以及与 .NET 的对应关系。
Windows I/O 的深层(第3回) ── I/O 完成端口(IOCP)与 .NET 线程池:async/await 的地下室
本文是通过图解讲解 I/O 完成端口(IOCP)的系列第 3 回。整理了将完成队列与线程数控制融为一体的设计、并发值与 LIFO 释放,直至 .NET 线程池与 async/await 续体的执行线程等内容。
相关主题
与本文相近的主题页面。以本文为起点,可以进一步了解相关服务和其他文章。
Windows 技术主题
汇整 KomuraSoft LLC 关于 Windows 开发、故障调查与既有资产活用文章的主题中心。
常见问题
汇总了咨询这一主题时常见的问题。
- 文件系统过滤器驱动程序与迷你过滤器有什么区别?
- 两者都是「介入对文件系统的 I/O 请求的驱动程序」,但介入方式的世代不同。旧式的传统过滤器,是在文件系统的设备栈上直接叠加自己的设备对象,由于位置由加载顺序决定,顺序难以保证,还存在一旦加载就无法安全卸载等问题。作为当前标准的迷你过滤器,则是向 Windows 自带的过滤器管理器(FltMgr)注册「希望在这个操作前后调用我」的回调。位置由被称为高度的编号确定性地决定,可以在任意时刻加载,若过滤器实现了卸载回调,还能在运行期间将其移除。杀毒软件・加密・监控工具・云同步等现代过滤器,几乎全部都以迷你过滤器的形式实现。
- 为什么杀毒软件能够检查所有的文件访问?
- 因为操作系统官方就预备了用于此目的的扩展点。迷你过滤器可以向过滤器管理器注册在打开・读取・写入等操作之前(pre 回调)和之后(post 回调)被调用的代码。杀毒软件的过滤器位于杀毒软件专用的高度区间(320000-329999),例如可以在文件打开成立的瞬间之后(post-create)扫描内容,发现问题就取消该次打开,使访问失败。正如本系列第 1 回所见,所有的文件 I/O 都会流经设备栈,因此只要站在这条必经之路上的固定位置,就能检查全部访问,道理就是这么简单。这不是黑客手段,而是内置在操作系统设计之中的机制。
- 杀毒软件的排除设置(文件夹排除)在技术上到底做了什么?
- 它让对匹配排除列表路径的 I/O,省略掉该产品过滤器所执行的扫描处理。过滤器本身并不会从栈中消失,更贴近实际情况的理解是:「这条路径不检查」这一判断被提前做出而已。有一个重要的限定:排除只对拥有该设置的产品自身生效。例如 Microsoft Defender 的排除设置改变的是 Defender 过滤器(WdFilter)的扫描,不会影响同时运行的其他厂商杀毒软件・EDR・备份等其他迷你过滤器的行为。每个产品都需要各自单独设置排除,「设置了排除却依然很慢」的情况,原因有可能出在别的过滤器上。另外,正如 Microsoft 文档反复警告的那样,排除会削弱该处的保护,因此应当与风险评估配套,控制在最小范围。在开发用途中,值得考虑的还有专为文件夹排除的安全替代方案而设计的 Dev Drive(性能模式=异步扫描)。
- Process Monitor 是如何记录所有 I/O 的?
- 因为 Procmon 自身会在启动时,把自己以 Activity Monitor(活动监视)专用高度区间的迷你过滤器身份,向过滤器管理器注册。在 Procmon 处于运行状态时,从具有管理员权限的命令提示符执行 fltmc,就能确认列表中出现了以 PROCMON 开头的过滤器名称。由于它作为迷你过滤器能够列席所有卷上 I/O 操作的 pre/post,因此能够毫无遗漏地记录下哪个进程对哪个文件执行了什么操作。本系列中出现过的 IRP 与快速 I/O 等术语之所以会原封不动地出现在 Procmon 的显示中,正是因为它站在了 I/O 通行本身的必经之路上进行观察。
- 当开发机器的构建变慢时,应该怀疑过滤器驱动程序吗?
- 非常值得怀疑。构建是大量小文件的创建・读写・删除的集合体,每一个操作都会成为过滤器群(特别是杀毒软件扫描)的检查对象,因此是过滤器成本最容易浮出水面的工作负载。排查的基本步骤是:在 Procmon 中查看 Duration 列,确认时间消耗在哪个操作上;再用 fltmc instances 对比不同环境之间过滤器构成的差异。对策方面,除了在评估风险之后设置排除以外,还可以考虑使用专为开发用卷设计的 Dev Drive。在 Dev Drive 上,杀毒软件会以性能模式(异步扫描)运行,Microsoft 将其定位为比排除设置更安全的替代方案。