65.9K
CodeProject 正在变化。 阅读更多。
Home

C++ 中的卷影复制服务 API 入门

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.72/5 (19投票s)

2012年1月30日

CPOL

7分钟阅读

viewsIcon

89398

downloadIcon

3667

C++ 中的卷影复制 API 入门

引言

卷影复制服务(Volume Shadow Copy Service,简称 VSS)为 Microsoft Windows 操作系统提供了备份基础结构,以及一种创建数据一致性时间点副本(称为卷影副本)的机制。VSS 在 Windows XP SP2 中引入,并可在 Windows Server 2003、Vista、Windows Server 2008、Windows 7 和 Windows Server 2008 R2 上使用。

卷影复制服务可以通过与应用程序、文件系统服务、备份应用程序、快速恢复解决方案和存储硬件协调,即使数据被锁定,也能生成一致的手动或自动备份副本或快照。Windows 操作系统中的一些功能会使用卷影复制服务。从 Vista 开始,某些组件(如名为“以前的版本”的属性表外壳扩展)允许从还原点本地恢复单个文件或文件夹,就像它们在快照创建时那样,从而检索文件的早期版本或恢复意外删除的文件。

本文将介绍如何使用原生 C++ 中的 VSS API 创建一个基本快照。MSDN 文档非常详尽,但说实话也有些令人费解,因此我萌生了写这篇文章的想法,希望能以一种更友好的方式来介绍 VSS API。

VSS 词汇

在编写代码之前,我们需要确定构成一个解决方案的不同组件。

  • VSS 服务

此组件是 Windows 的一部分,它确保其他组件能够正确地相互通信并协同工作。

  • VSS 请求程序

这是本文的重点。它只是一组用于创建、导入或删除卷影副本的指令。一个典型的例子是像 NTBackup 这样的备份应用程序。在 Vista 或 Win 7 和 Win 2008 上,Windows Server Backup 实用程序和 System Center Data Protection Manager 应用程序是 VSS 请求程序。本系列的第一部分将重点介绍 VSS 请求程序的基础知识。

  • VSS 写入程序

VSS 写入程序是一个软件组件,通过接收 冻结和解冻通知,确保备份的数据文件在内部一致,从而保证备份的数据集一致。SQL Server® 或 Exchange Server 用户熟悉 VSS 写入程序,因为这两个应用程序都带有自己的写入程序。Windows 还为注册表等各种组件包含了一些 VSS 写入程序。如果您想确保备份期间数据的完整性,可以为自己的应用程序创建 VSS 写入程序。本文的第二部分将介绍 VSS 写入程序。

  • VSS 提供程序

此组件负责创建和维护卷影副本。这可以在软件或硬件层面进行。Windows 操作系统包含一个使用写时复制的 VSS 提供程序。如果您使用存储区域网络 (SAN),那么安装 SAN 的 VSS 硬件提供程序非常重要,如果它可用的话。硬件提供程序将创建和维护卷影副本的任务从主机操作系统中卸载。在本文中,我将提及 VSS 提供程序,但要了解更多关于它的信息,请访问 MSDN 页面。

它是如何工作的?

现在我们知道了请求程序、写入程序和提供程序是什么,那么如何将它们的作用置于上下文中,并展示它们如何相互作用来创建一个快照

无论副本的具体用途和使用 VSS 的应用程序如何,卷影副本的创建都遵循相同的步骤:

  1. 请求程序请求卷影复制服务枚举写入程序、收集写入程序元数据,并为卷影副本的创建做好准备。
  2. 每个写入程序都会创建一个 XML 描述需要备份的组件和数据存储,并将其提供给卷影复制服务。写入程序还定义了一个用于所有组件的还原方法。卷影复制服务将写入程序的描述提供给请求程序,请求程序选择将被备份的组件。这部分将在第二部分介绍。
  3. 卷影复制服务通知所有写入程序准备其数据以创建卷影副本。
  4. 每个写入程序会相应地准备数据,例如完成所有打开的事务、滚动事务日志和刷新缓存。当数据准备好进行卷影复制时,写入程序会通知卷影复制服务。
  5. 写入程序会暂时冻结应用程序写入 I/O 请求,以进行创建卷影副本卷或卷所需的几秒钟。请注意,在此期间,读取 I/O 请求仍然是可能的。应用程序冻结不允许超过 60 秒。卷影复制服务会刷新文件系统缓存,然后冻结文件系统,这确保了文件系统元数据被正确记录,并且要进行卷影复制的数据以一致的顺序写入。
  6. 然后由提供程序创建卷影副本。此操作持续不超过 10 秒,在此期间,对文件系统的所有写入 I/O 请求都保持冻结状态。
  7. VSS 服务释放文件系统写入 I/O 请求,并 指示写入程序解冻应用程序写入 I/O 请求。

编写代码

现在是时候深入研究 API 了。我假设您了解我的开发环境。VSS 可在 Microsoft Windows SDK 中找到。如果您使用的是 Windows Server 2003 和 Windows XP,则必须使用卷影复制服务 7.2 SDK。Windows XP 有一个限制:创建的快照不是持久的。本文的代码是使用 Visual C++ 2010 和 Windows SDK 7.1 编译的,并在 Windows Vista 和 Windows 7 上进行了测试。还有一点需要知道的是,所有 VSS 应用程序(请求程序、提供程序和写入程序)都必须作为原生的 32 位或 64 位应用程序运行。在 WOW64 下运行它们不受支持。

VSS API 假定了解 COM(中级)。

自制请求程序的接口:IVssBackupComponents

无论您是想运行备份、还原还是获取有关快照的信息,您都必须实现一个请求程序。所有请求程序都使用 IVssBackupComponent 接口。应用程序使用此接口的实例来轮询写入程序,了解文件状态,并运行备份或还原操作。应用程序通过调用 CreateVssBackupComponents 来获取 IVssBackupComponents 接口的实例。

 // Create the IVssBackupComponents Interface
IVssBackupComponents *pVssBackup = NULL;
HRESULT hr = CreateVssBackupComponents(&pVssBackup);
if (result = S_OK) {. . .
... 
 

创建快照

任何卷影副本的创建都将始终需要 IVssBackupComponents::InitializeForBackupIVssBackupComponents::StartSnapshotSet 方法。

// sets the context for subsequent shadow copy-related operations.
HRESULT result = pVssBackup->InitializeForBackup(); 
if (result == S_OK){
                    . . 
}. 

尽管请求程序可以创建不同类型的卷影副本,但大多数备份应用程序会调用以下方法:

1. 调用 IVssBackupComponents::SetContext

上下文为 VSS_CTX_BACKUP。

 // sets the context for subsequent shadow copy-related operations.
HRESULT result = pVssBackup->SetContext(VSS_CTX_BACKUP | VSS_CTX_CLIENT_ACCESSIBLE_WRITERS                                        | VSS_CTX_APP_ROLLBACK);
if (result == S_OK) {. . . 
2. 调用 IVssBackupComponents::GatherWriterMetadata 来初始化与写入程序的通信。
// sets the context for subsequent shadow copy-related operations.
<pre>IVssAsync *pAsync = NULL;
HRESULT result = pVssBackup->GatherWriterMetadata(&pAsync);
if (result == S_OK) 
{ 
}
// Free all resources allocated during the call to GatherWriterMetadata
pVssBackup->FreeWriterMetadata();
//  

3. IVssBackupComponents::StartSnapshotSet 初始化卷影复制机制。

VSS_ID snapshotSetID;
HRESULT result = pVssBackup->StartSnapshotSet(); 
if (result == S_OK) {. . . 

VSS_ID 定义指定了通用的 VSS 标识符格式。它是一种标准的 GUID 数据类型,用于标识卷影副本、卷影副本集、提供程序、提供程序版本、写入程序。

4. 调用 IVssBackupComponents::AddToSnapshotSet 将卷添加到卷影副本中。
TCHAR szVolumeName[MAX_PATH]; // DO NOT FORGET TO INITIALIZE IT!!!
HRESULT result = pVssBackup->AddToSnapshotSet(szVolumeName , GUID_NULL, &snapshotSetID); 
if (result == S_OK) {. . .  

第一个参数可以是卷的名称或要进行卷影复制的远程文件共享的 UNC 路径。它必须符合以下格式之一,并且必须包含尾部反斜杠 (\)

  • 挂载文件夹的路径,例如 Y:\MountX\
  • 驱动器号,例如 D:\
  • 格式为 \\?\Volume{GUID}\ 的卷 GUID 路径(其中 GUID 标识卷)
  • 指定远程文件共享的 UNC 路径,例如 \\Clusterx\Share1\

5. 调用 IVssBackupComponents::PrepareForBackup 以通知写入程序进行备份操作。

IVssAsync *pAsync = NULL; 
HRESULT result = pVssBackup->PrepareForBackup(&pAsync); 
if (result == S_OK) {. . . 

本文附带的演示项目包含了创建快照的代码。

处理快照

Windows XP 及更高版本包含一个名为 vssadmin 的命令行实用程序,可用于操作卷影副本。此实用程序需要管理员权限。

命令 _vssadmin list shadows /for=c:\_ 将返回驱动器 C:\ 上所有卷影副本的列表。

在 Vista 及更高版本上,可以通过输入命令将这些副本挂载到 Windows 资源管理器中

_mklink /d c:\mount_shadow_copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopyX\_ 。X 是上一个命令返回的任意数字。

您想以编程方式挂载卷影副本吗?那么 CreateSymbolicLink 函数就是您的答案。本文附带的代码中有一个注释掉的示例。请注意,此函数仅在 Vista、Win7 和 Win 2k8 上可用。

敬请期待

第一部分的 VSS 系列到此结束。我将带着另一篇关于高级请求程序和 VSS 写入程序的文章回来。祝您编码愉快。

© . All rights reserved.