事务 NTFS 的编程注意事项
有关事务 NTFS 的各种编程注意事项的说明,请参阅以下部分:
要处理哪些文件更改
大多数文件更改(例如对文件内容、流、重分析点、属性和文件系统命名空间的更改)都是事务处理。 当对事务处理的文件句柄进行其中一项更改时,更改将与其他事务隔离,如果回滚事务,更改将撤消。
不影响文件内容、元数据或文件系统命名空间的更改(如压缩或碎片整理的更改)不会被事务处理。 这些更改不会与其他事务隔离,如果回滚事务,这些更改也不会撤消。
压缩
不能更改事务中打开的文件的压缩状态。
创建文件或目录
在事务中创建的文件或目录对当前事务外部的任何内容都不可见。 在此事务之外,创建同名文件的任何尝试都失败, 并ERROR_TRANSACTIONAL_CONFLICT错误,从而在事务提交或回滚时有效地保留文件名。
删除文件
通过调用 DeleteFileTransacted 函数删除的文件或目录对所有外部读取器都保持可见。
注意
必须在事务结束前关闭文件的所有事务处理句柄。 如果未正确关闭句柄,则不会进行删除。 在执行提交之前,必须关闭文件的所有打开句柄,才能将删除操作视为事务的一部分。 这是因为,在关闭文件的最后一个句柄之前,系统不会实际删除文件,即使未将操作作为 Windows 文件 I/O 子系统的一部分进行事务处理也是如此。
删除目录
通过调用 RemoveDirectoryTransacted 函数删除的目录对所有外部读取器保持可见。
注意
对于事务处理目录操作的打开句柄,约束与对文件的约束相同。 有关详细信息,请参阅 删除文件。
目录锁定问题
如果在事务中修改了文件,则该文件路径的所有目录组件都称为 “针对重命名固定 ”,直到事务结束。 也就是说,在提交或回滚事务之前,系统会阻止你重命名它们。 尝试将上级目录重命名为已在正在进行的事务中修改的文件将失败 ,并ERROR_CANT_BREAK_TRANSACTIONAL_DEPENDENCY错误。
目录枚举
由于使用枚举的 API(例如 FindFirstFileTransacted 和 FindNextFile 函数),当枚举正在进行时,可以更改目录的内容。
对事务外部目录的更改不会与事务隔离,并且立即在事务中可见。 例如,如果非事务编写器将文件添加到目录,则新文件在事务中立即可见,因此调用 FindFirstFileTransacted 或 FindNextFile 函数将返回新文件。
在事务提交之前,对事务中的目录所做的更改是隔离的。 例如,在 目录中作为事务的一部分创建的文件。 调用 FindFirstFile 或 FindNextFile 函数的非事务读取器在事务提交之前不会看到新创建的文件。
内存映射文件
客户端必须调用 FlushViewOfFile 函数、关闭文件映射对象并关闭文件句柄,然后才能在内存映射文件上提交关联的事务。
命名的流
命名流是完全事务性的,但锁定是在文件级别而不是流级别完成的。 尝试修改锁定文件中任何流的事务外部的编写器会收到 错误ERROR_SHARING_VIOLATION。
不能重命名事务中的辅助流。
重命名文件或目录
若要将文件重命名为事务处理操作,请调用 MoveFileTransacted 以移动文件。
重分析点
对重新分析点的更改是交易的,这意味着,如果将新的重新分析点分配给事务中的文件,则其他事务不可见。 同样,对现有重新分析点的更改或删除在提交之前是不可见的。
错误代码
内核事务管理器 (KTM) 使用 6700 到 6799 范围内的系统错误代码。 事务 NTFS (TxF) 使用 6800 到 6899 范围内的 Windows 错误代码。 有关详细信息,请参阅 WinError.h 和系统错误代码 (6000-8199) 。
加密文件系统
TxF 不支持对 EFS 文件执行的操作。 不能为事务打开 EFS 加密的文件。 对 EFS 文件调用 CreateFileTransacted 函数将失败, 并ERROR_EFS_NOT_ALLOWED_IN_TRANSACTION错误。 同样,对事务中的文件调用 EncryptFile 函数将失败, 并ERROR_EFS_NOT_ALLOWED_IN_TRANSACTION错误。
文件 I/O 函数和事务 NTFS
TxF 提供采用文件名的新事务处理函数,并更改采用文件句柄的现有文件 I/O API 函数的行为。
事务处理函数
如果不调用以下事务处理函数之一来代替其非事务处理版本,则不会执行该操作:
- CopyFileTransacted
- CreateDirectoryTransacted
- CreateFileTransacted
- CreateHardLinkTransacted
- CreateSymbolicLinkTransacted
- DeleteFileTransacted
- FindFirstFileNameTransactedW
- FindFirstFileTransacted
- FindFirstStreamTransactedW
- GetCompressedFileSizeTransacted
- GetFileAttributesTransacted
- GetFullPathNameTransacted
- GetLongPathNameTransacted
- MoveFileTransacted
- RemoveDirectoryTransacted
- SetFileAttributesTransacted
例如, CreateFile 函数现在具有事务处理版本: CreateFileTransacted。
TxF 更改的文件 I/O 函数
下表列出了其行为受事务 NTFS 影响的函数。 例如,ReadFile 函数的行为将有所不同,具体取决于 hFile 参数是由 CreateFile 函数还是 CreateFileTransacted 函数创建的。
函数 | 说明 |
---|---|
CloseHandle |
在提交事务之前,应用程序应关闭绑定到事务的所有句柄。 在提交事务之前,应用程序必须关闭使用 FILE_FLAG_DELETE_ON_CLOSE 打开的交易句柄,才能执行删除操作。 |
CreateFileMapping |
如果存在与 hFile 关联的事务,则此函数创建的文件映射对象将与同一事务相关联。 通过此文件映射对象的视图进行的修改将进行事务处理。 在提交事务性更改之前,应用程序必须调用 FlushViewOfFile、取消映射所有视图并关闭文件映射对象的所有句柄。 |
FindNextFile |
如果有绑定到文件枚举句柄的事务,则返回的文件受事务隔离规则的约束。 |
FSCTL_SET_COMPRESSION |
不能更改 CreateFileTransacted 打开的文件的压缩状态。 |
GetFileInformationByHandle 和 GetFileInformationByHandleEx |
如果有绑定到文件句柄的事务,则该函数将返回独立文件视图的信息。 |
GetFileSize 和 GetFileSizeEx |
如果有绑定到文件句柄的事务,则该函数将返回独立文件视图的信息。 |
GetVolumeInformation |
如果卷支持文件系统事务,则函数在 lpFileSystemFlags 中返回FILE_SUPPORTS_TRANSACTIONS。 |
MapViewOfFile 和 MapViewOfFileEx |
如果存在与用于创建正在映射的文件映射对象的文件句柄关联的事务,则关联视图将事务处理。 如果视图用于对文件进行事务性更改,则用户必须调用 FlushViewOfFile,关闭文件映射对象,并在提交关联的事务之前关闭文件句柄。 |
ReadDirectoryChangesW |
如果有绑定到目录句柄的事务,则通知会反映目录的独立视图。 通知中不包括对目录事务视图之外的文件的更改。 |
ReadFile、 ReadFileEx 和 ReadFileScatter |
如果有绑定到文件句柄的事务,则该函数将从文件的事务处理视图中返回数据。 事务处理读取句柄保证在句柄期间显示相同的文件视图。 |
SetEndOfFile |
如果有绑定到句柄的事务,则会处理文件末尾位置的更改。 |
SetFileInformationByHandle |
如果有绑定到句柄的事务,则将对信息类 FileBasicInfo、FileRenameInfo、FileAllocationInfo、FileEndOfFileInfo 和 FileDispositionInfo 进行事务处理所做的更改。 |
SetFileShortName |
如果有绑定到句柄的事务,则文件的短名称更改将进行事务处理。 |
SetFileTime |
如果有绑定到句柄的事务,则会处理文件时间中的更改。 |
WriteFile、 WriteFileEx 和 WriteFileGather |
如果有绑定到文件句柄的事务,则文件写入将事务处理。 |