网络重定向程序使用机会锁 (oplock) 来优化文件访问性能,减少客户端-服务器环境中的网络流量。
本文档面向网络重定向程序开发人员,但某些信息也适用于客户端应用程序开发人员。 有关客户端应用程序的更多 oplock 文档,请参阅 Windows SDK 的机会锁文章。
Oplock 概述
机会锁(opportunistic lock)是客户端对驻留在服务器上的文件加上的一种锁。 在大多数情况下,客户端会请求一个 oplock,以便在本地缓存数据。 具有远程服务器的客户端上的网络重定向程序使用 oplocks,而本地服务器上的客户端应用程序也使用 oplocks。 有关各种当前和旧版 oplock 的描述,请参阅 oplock 类型。
Oplock 允许文件服务器客户端(如使用 SMB 和 SMB2 协议的客户端)以一致的方式动态更改给定文件或流的缓冲策略。 使用 oplock 可以提高性能,减少网络使用。 为了提高远程文件操作的网络性能,客户端可以在本地缓冲文件数据,从而减少或消除发送和接收网络数据包的需要。 例如:
- 如果客户端知道没有其他进程在访问远程服务器上的数据,那么客户端可能就不必将信息写入该文件中。
- 如果客户端知道没有其他进程正在向远程文件写入数据,则可以缓冲来自远程文件的预读数据。
应用程序和驱动程序还可以使用 oplock 来透明地访问文件,而不会影响可能需要使用这些文件的其他应用程序。
NTFS 等文件系统支持每个文件多个数据流。 系统在流句柄上授予 oplock,这意味着系统为给定打开的文件流授予 oplock,操作适用于该流。 除了少数例外情况,对一个数据流的操作不会影响另一个数据流上的 oplock。 有关详细信息,请参阅请求和授予 oplock。
对于不支持备用数据流的文件系统(如 FAT),当 oplock 讨论提到“流”时,应想到是“文件”。
内核实现 oplock 包的核心 oplock 功能,主要是通过 FsRtlInitializeOplock 等 FsRtlXxx 例程实现。 文件系统会调用该包,以在其文件系统中实现 oplock 功能。 本部分中的 oplock 文章介绍了 NTFS 文件系统如何与内核 oplock 包互操作。 其他文件系统的功能与此类似,但可能存在细微差别。
Oplock 密钥
可以将流句柄与 oplock 键相关联,这是一个 GUID 值,用于标识属于同一客户端缓存视图的多个句柄。 更准确地说,oplock 密钥与流句柄指向的 FILE_OBJECT 结构相关联。 复制句柄(例如使用 DuplicateHandle)时,此区别非常重要。 每个重复句柄都指向相同的基础 FILE_OBJECT 结构。
创建流句柄时,可以显式提供 oplock 键(到 IoCreateFileEx)。 如果未在创建句柄时显式指定机会锁密钥,系统将该句柄视为具有唯一的机会锁密钥与之关联。 这个独一无二的密钥不同于任何其他句柄上的密钥。
如果满足以下所有条件,则 oplock 中断:
- 在除授予 oplock 的句柄之外的其他句柄上接收到文件操作。
- 与 oplock 句柄关联的 oplock 键不同于与操作句柄关联的键。
- 该操作与当前授予的 oplock 不兼容。
即使同一进程或线程执行不兼容的操作,Op锁也会中断。 例如,当独占 oplock 立即中断时:
- 进程打开一个已被授予独占 Oplock 的数据流。
- 同一进程使用不同的(或没有)机会锁密钥再次打开同一流。
有关详细信息,请参阅中断 oplock。
请记住,作锁键存在于句柄上,并在创建句柄时将其“置于”句柄上。 即使没有授予 oplock 密钥,也可以将句柄与 oplock 密钥关联。