申请号:CN102736948 B
申请日期:2011年12月19日
申请人:微软公司
【摘要】
本发明涉及用于设置检查点并恢复程序状态的方法。此处描述了允许从检查点恢复被中断的程序执行而无需来自计算机操作系统的协作的技术。这些技术可通过使用自动化工具修改现有代码来实现,该自动化工具添加用于允许恢复中断的程序执行的指令。
【技术领域】
[0001] 此处所描述的技术涉及允许从中断点恢复计算机进程的执行。
【权利要求(9)】
1. 一种用于设置检查点并恢复程序状态的方法,包括: 接收(402)被配置成控制微处理器来执行一个或多个操作的第一计算机可读指令; 使用微处理器,基于所述第一计算机可读指令来生成(404)第二计算机可读指令,所 述第二计算机可读指令被配置成执行一个或多个操作并且通过以下步骤来从检查点恢复 函数的执行: i) 调用所述函数(304); ii) 加载数据供所述函数使用(306),在所述函数之前的执行期间所述数据已在所述 检查点被保存;以及 iii) 跳至所述函数的在所述函数之前的执行期间在所述检查点处曾在执行的行 (308),所述函数的该行是所述函数中非所述函数的开始或结尾的一点,并且 其中生成所述第二计算机可读指令包括将附加指令添加至所述第一计算机可读指令, 所述附加指令被配置成从检查点恢复所述函数的执行。
如权利要求1所述的方法,其特征在于,所述方法通过编译器来执行,所述编译器将 包括所述第一计算机可读指令的源代码编译成包括所述第二计算机可读指令的对象代码。
如权利要求1所述的方法,其特征在于,所述第二计算机可读指令还被配置成保存 所述函数所使用的数据(204)。
如权利要求1所述的方法,其特征在于,所述第二计算机可读指令还被配置成跟踪 包括所述函数的程序的程序栈(120)。
-种用于设置检查点并恢复程序状态的系统,包括: 用于接收被配置成控制微处理器来执行一个或多个操作的第一计算机可读指令的装 置; 用于使用微处理器,基于所述第一计算机可读指令来生成(404)第二计算机可读指令 的装置,所述第二计算机可读指令被配置成执行一个或多个操作并且通过以下步骤从检查 点恢复函数的执行: i) 调用所述函数; ii) 加载数据供所述函数使用,在所述函数之前的执行期间数据已在所述检查点被保 存; iii) 跳至所述函数的在所述函数之前的执行期间在所述检查点处曾在执行的行,所述 函数的该行是所述函数中非所述函数的开始或结尾的一点,并且 其中所述生成所述第二计算机可读指令的装置包括用于将附加指令添加至所述第一 计算机可读指令的装置,所述附加指令被配置成从检查点恢复所述函数的执行。
如权利要求5所述的系统,其特征在于,所述微处理器包括第一微处理器(602)和第 二微处理器(604)。
如权利要求6所述的系统,其特征在于,所述第一微处理器执行所述函数,并且,当 使用所述第一微处理器¢02)的函数的执行被中断时,所述函数的执行使用所述第二微处 理器(604)从所述检查点继续。
如权利要求7所述的系统,其特征在于,所述第一微处理器(602)被包括在第一设备 (601)中;以及 所述第二微处理器(604)被包括在第二设备(603)中。
9.如权利要求8所述的系统,其特征在于所述第一设备运行第一操作系统并且所述第 二设备运行与所述第一操作系统不同的第二操作系统。
【背景技术】
[0002] 已知在应用程序或其它计算机程序非预期地终止或不再按设计地运行的情况下 发生程序崩溃。一些程序不时地保存信息,使得当崩溃发生时,能够限制数据丢失的量。例 如,当用户在做文档工作时,一些文字处理程序在不同时间自动保存文档的草稿。如果文字 处理程序崩溃了,则用户可以能够通过加载文字处理程序自动保存文档的最近的点处的保 存的数据来恢复文档。
[0003] -些操作系统提供当程序正在运行时从程序接收信息的能力,并且可从所保存的 状态恢复程序的执行。然而,在这些技术中,要求来自操作系统的协作以允许程序的执行被 恢复。
【发明内容】
[0004] 如以上所讨论的,一些用于从中断点恢复程序的执行的现有技术要求来自操作系 统的协作。这些技术要求操作系统提供适合用于保存应用数据以及当执行中断时恢复应用 的运行的状态的接口。然而,不是所有的操作系统都提供这种能力。提供在应用级恢复程 序的执行而无需要求来自操作系统的协作将是有利的。
[0005] -些应用已被特别地设计和编程为包括保存程序数据并且当执行被中断时恢复 程序数据的能力。然而,对于应用程序员来说在写新程序或修改现有程序时不得不设计和 编写一个应用以提供这种能力将是耗费时间的。
[0006] 此处所描述的技术提供了一种程序级的灵活的框架,用于允许设置检查点以及程 序执行的恢复。申请人已开发了用于从执行被中断的点处恢复程序执行而无需来自计算机 的操作系统的协作的技术。这些技术可在程序级被实现,而不考虑程序所运行在的操作系 统环境。在一些实施例中,可采用自动化工具将实现这些技术的代码结合到现有的程序代 码中,该自动化工具修改程序并添加用于运行恢复中断的程序执行的指令。由此,开发应用 的程序员不需要设计或编写应用代码以包括这些特征,因为用于允许恢复中断的程序执行 的代码可使用自动化工具被自动结合。
[0007] -些实施例涉及一种方法,包括:接收被配置成控制微处理器来执行一个或多个 操作的第一计算机可读指令;使用微处理器,基于第一计算机可读指令来生成第二计算机 可读指令,第二计算机可读指令被配置成执行一个或多个操作并且通过调用函数来从检查 点恢复函数的执行;加载数据供函数使用,在函数之前的执行期间数据已在该检查点被保 存;以及跳过在抵达该检查点之前在函数之前的执行期间被执行的一部分函数。一些实施 例涉及计算机可读存储介质,其上存储了执行时执行上述方法的指令。
[0008] -些实施例涉及一种方法,包括:一种其上存储计算机可读指令的计算机可读存 储介质,计算机可读指令被配置成通过调用函数从检查点恢复函数的执行;加载数据供函 数使用,在函数之前的执行期间数据已在该检查点被保存;跳过在抵达该检查点之前在函 数之前的执行期间被执行的一部分函数;保存该函数所使用的数据;以及跟踪包括该函数 的程序的程序栈。系统还包括至少一个被配置成执行计算机可读指令的微处理器。
[0009] 以上是一些实施例的非限制性概述。
附图说明
[0010] 在附图中,各个附图中示出的每个相同或近乎完全相同的组件由同样的附图标记 来表示。出于简明的目的,不是每个组件在每张附图中均被标记。附图不一定是按比例的, 相反,重点放在示出本发明的各方面上。
[0011] 图1示出了根据一些实施例的包括用于执行作为计算机程序的函数F的一部分的 操作的计算机可读指令的软件模块的图表。
[0012] 图2示出根据一些实施例的执行包括保存各检查点处的程序状态和程序数据的 程序的流程图。
[0013] 图3显示根据一些实施例的用于从检查点重建函数的执行的方法的流程图。
[0014] 图4显示了根据一些实施例的用于修改代码以允许从检查点恢复程序的运行的 方法的流程图。
[0015] 图5显示了具有在其上能够实现此处所描述的技术的多个微处理器的技算设备 的示例。
[0016]图6显示了包括在其上能够实现此处所描述的技术的技算设备的计算环境的示 例。
具体实施方式
[0017] 如以上讨论的,此处所描述的技术允许当执行中断时从检查点恢复程序执行,而 无需来自计算机的操作系统的协作。这些技术可针对底层硬件或软件中的不稳定性进行保 护,并且可允许在操作系统崩溃、断电、或系统中的其它故障之后恢复程序执行。这些技术 可通过使用自动化工具修改现有代码来实现,而无需要求程序员特别编写应用以包括这一 功能。在一些实施例中,编译器或其它程序翻译工具可重新配置现有代码以提供保存并在 错误发生之后恢复程序执行的能力。
[0018] 有利地,这些技术在多线程、多核环境中以及其中程序运行在多个机器上的环境 中可以是稳固的。当执行被中断并且不能够继续时,程序可在一不同的处理器或一不同的 机器上、甚至在一运行不同操作系统的机器上继续执行。这些技术可被有利地用于云计算 环境,其中多个机器可用于执行一个程序。以下将提供示例性实施例的详细讨论。
[0019] I.修改稈序代码以支持恢复执行的示例
[0020] 常用的程序语言提供定义在程序的执行期间可能被调用的函数的能力。代码定义 了函数的关键方面,诸如函数接受的输入、函数执行的操作、以及函数返回的数据。
[0021] 例如,以下代码定义函数F和G。函数F接收整数a和b作为输入。函数F将局 部变量X初始化为被设为等于a·b的积的整数,并且将变量y初始化为被设为等于函数G的返回值的整数。函数F返回具有值x+y的整数。函数G接收整数X和b作为输入,X和b 分别对应于函数G内的局部变量a和b。函数G将局部变量X初始化为被设为等于a+b的 整数。函数G返回等于X的值的整数。
[0022]
Figure CN102736948BD00061
[0023]当运行程序时,函数F可被调用,函数F随后调用函数G。如果在函数F和/或G的执行期间程序崩溃或以执行其它方式中断,执行函数F和/或G中取得的进展可能丢失。 为了继续执行,程序需要被重新启动并且函数F需要被从头开始再次启动,并且随后函数G 需要被再次调用。尽管执行示例性函数F和G所需的处理能力可能不大,但应当理解,当执 行复杂程序时,可能丢失大量的数据并且可需要第二次执行大量的处理来抵达函数F和/ 或G的执行曾被中断的点。当执行诸如例如建模和模拟之类的复杂的编程任务时,丢失的 工作的量可能特别大。
[0024] 在一些实施例中,可将附加代码插入到程序中以允许在被称为”检查点”的各个点 存储程序的运行状态。可包含代码,用于通过保存关于哪些函数正运行的指示来跟踪程序 栈。可还包括代码,用于存储函数所使用的局部变量以及用于保存函数内的在执行中已到 达的行的指示。这些类型的代码的添加通过调用在检查点处正在运行的一个或多个函数、 加载该函数正使用的局部变量、以及跳过函数在中断前已被执行的部分,可允许重建程序。
[0025] 图1显示了软件模块100的示例,软件模块100包括用于执行计算机程序的函数 F的操作以及用于允许恢复程序执行的计算机可读指令。软件模块100的计算机可读指令 允许跟踪程序内函数执行的状态、保存程序执行期间在各检查点处函数所使用的数据、以 及当程序中断时从检查点恢复函数的执行。在图1的示例中,软件模块100包括帮助器代 码102、函数前言(preamble) 104、用于执行函数F的操作的函数代码106、调用位置标签代 码(callsitelabelcode) 108,以及函数结尾 110。
[0026] 帮助器代码102可包括定义用于保存函数F的局部变量和输入自变量的数据结构 的代码112。帮助器代码102还可包括代码114和代码116,代码114定义用于保存函数F 的数据的保存函数,代码116定义用于从存储器中加载函数F的数据的加载函数。保存函 数将所保存的变量附加到检查点文件。加载函数从检查点文件中的当前点加载变量并使文 件指针向前。尽管为了例示概念的目的显示为软件代码,但可以理解的是,帮助器代码102 和此处所描述的任何其它代码可被实现为对象代码,或任何其它适当类型的代码。以下示 出适合用于定义数据结构并提供保存和加载函数的帮助器代码102的示例。
[0027]
Figure CN102736948BD00071
[0028] 图1中所示,函数前言104可包括代码118和代码120,代码118实例化用于函数 F的局部变量的数据结构对象,代码120用于通过使用pushO函数保存正被执行的函数F 的指示来跟踪程序栈。函数前言104还可包括能够从检查点重建函数F的执行的代码122。 如果函数F的执行正被重建,执行代码124来加载曾在检查点保存的函数F的局部变量。 代码126被执行以跳过函数F中在抵达检查点之前已执行过的部分。例如,如果当程序的 执行被中断时函数G正在函数F的范围内执行,代码126可跳至函数F的调用函数G的行。 以下显示可用于一些实施例中的函数前言104的示例。
[0029]
Figure CN102736948BD00081
[0030] 如图1所示,包含函数代码106用于执行函数(例如函数F)的操作。虽然通过示 例的方式讨论了函数F,此处所描述的函数可被用于任何执行计算机程序的一个或多个操 作的函数。函数代码106可根据原始函数(例如函数F)的函数代码来重写,使得局部变量 被存储在代码112所定义的数据结构中以便于在执行期间保存数据,使得如果需要重建函 数F的执行时变量可稍后被加载。以下示出了用于一些实施例中的函数代码106的示例。
[0031]I.X=a*b;
[0032] 如以上针对函数F所讨论的,变量X被设为等于积a*b。在函数代码106中,执行 与函数F中相同的乘法运算,但是代码被修改使得结果被存储在代码112所定义的数据结 构中,以便于如果函数需要被重建时重新加载局部变量。
[0033] 如图1所示,调用位置标签代码130可包括标识函数F内在何处调用其它函数的 代码。例如,函数F可调用另一函数G,并且调用位置标签代码130可标识函数F内函数G 被调用的位置。代码132也被包括在函数F中用于调用函数G。以下示出了用于一些实施 例中的调用位置标签函数代码130的示例。
[0034]FunctionCalll:
[0035] 1.-CallSite= 1;
[0036]I.y=G(l.X,b);
[0037] 在这点处,可包括附加函数代码106,如以下所示,附加函数代码106可被执行以 计算变量X和y的和,如以上函数F所示。
[0038]inttemp=I.x+1.y;
[0039] 如图1中所示,函数结尾110可包括代码134用于在函数F的执行将要完成时使 用pop0函数来更新对程序栈的跟踪。函数尾声110还可包括代码136用于通过函数F返 回数据。以下显示可用于一些实施例中的函数尾声110的示例。
[0040]
Figure CN102736948BD00091
[0041] 以下代码定义了”Checkpoint(检查点)”类的示例,其具有LoadLocalsO和 SaveLocals()的实现,LoadLocals()和SaveLocals()进一步被 “Locals” 对象的Load() 和SaveO方法所使用。
[0042]
Figure CN102736948BD00092
[0043]
Figure CN102736948BD00101
[0044] II.在检杳点保存稈序状杰的示例
[0045] 图2显示了执行程序并在各个检查点保存程序状态的方法200的示例。为了保 存程序状态,局部对象的栈可被遍历并且每个对象可依次被保存。程序的执行开始于步骤 202。在步骤203,抵达检查点时机,此处程序具有对保存程序的状态选项。程序可在步骤 203做出决定是否利用该检查点机会来保存程序状态。可基于从上次检查点以来经过的时 间量,或其它任何适当的标准,来做出程序是否使用该检查点机会的决定。在一些情况下, 用户可明确请求检查点。在保存程序状态的频率和程序的性能之间存在权衡。增加保存程 序状态的频率可限制数据丢失的量,但可引起降低的程序性能。把握检查点机会的频率可 随着应用而改变。
[0046] 如果程序决定使用该检查点机会来保存程序状态,该信息在步骤204中被保存。 例如,程序可使用由帮助器代码102中的由代码114所定义的保存函数。如果程序决定不 使用该检查点机会,则程序的执行在步骤206继续。程序的执行继续直到抵达下一检查点, 在该点方法返回到步骤203的下一检查点机会。方法200可继续直至程序终止。
[0047] III.从检杳点恢复稈序执行的示例
[0048]图3显示根据一些实施例的用于从检查点恢复函数执行的方法300的流程图。在 步骤302,在发生崩溃或其它故障之后重启程序。在步骤304,程序调用第一函数,诸如以上 讨论的函数F。在步骤306从存储中加载在检查点保存的函数F的局部变量。在步骤308, 程序跳到函数F的在检查点处曾在执行中的行,并且函数F的执行从那一点恢复。因此,步 骤306和308便于当在检查点存储了程序状态时将函数F的执行恢复到该执行点。如果在 该检查点处函数G曾在执行,程序可跳至函数F的调用函数G的行,并且随后在步骤310调 用函数G。随后为函数G重复步骤306和308。从存储中加载曾在该检查点保存的函数G 的局部变量,并且程序跳至函数G的在该检查点处曾在执行的行。如果在之前的函数的范 围内没有其它曾在执行的函数,方法结束并且程序执行从该检查点继续。因此,程序的执行 可从该检查点恢复而无需要求执行抵达该检查点之前、在程序的中断之前的所执行的所有 操作。
[0049] IV.牛成允许保存状杰并从检杳点恢复稈序执行的代码
[0050]图4例示了根据一些实施例的用于修改代码以允许从检查点恢复程序的运行的 方法。如上所讨论的,此处所描述的技术有利地能够被自动结合入程序中而无需程序员手 动编码。诸如编译器之类的程序翻译工具可修改现有代码以允许从检查点恢复程序的运 行。例如,在步骤402,编译器或其它程序翻译工具能够接收包括定义一个或多个函数的代 码的程序代码。程序代码可被设计成执行任何适当的操作,因为此处所描述的技术不对程 序所执行的操作的类型进行限制。作为一个示例,程序代码可包括定义函数F和G的代码, 如以上所讨论的。在步骤404,用于执行函数F和G的代码被修改为允许程序从检查点恢复 执行。例如,编译器或其它程序翻译工具可插入如以上所讨论的帮助器代码102、函数前言 104、调用位置标签代码108、以及函数结尾110。检查点机会还可被插入在代码内的合适位 置用于保存数据。函数代码106可被修改以利用数据结构来存储帮助器代码102中所定义 的局部变量。如果编译器被用于执行方法400,所产生的结果可以是被配置成执行函数F和 G的对象代码,具有允许在中断发生时从检查点恢复函数F和G的执行的附加能力。
[0051] V.应用稈序
[0052]此处所描述的技术可提供错误容忍和失效备援方案,这对于具有长执行时间的程 序可以是非常意义重大的。这是因为随着计算的规模增长而增加的丢失工作的成本。这些 技术还可以对利用大量计算资源的分布式程序非常有用,因为当越多的硬件被用于执行计 算,故障的可能性越高。新的计算机硬件中的趋势已经从每个下一代硬件指数式地更快这 样的范例变为每个下一代具有指数式地更多计算核心这样的范例。此处所描述的技术可被 用于允许使用运行在多个计算核心或一个群集的机器上的多线程程序来执行大量的计算 工作。例如,该技术可被用于云技术环境,在云计算环境中多个机器和/或多个核心被涉及 用于处理程序数据。
[0053]此处所描述的技术的优点是可在一个处理器/机器上启动程序,且随后在崩溃或 其它故障发生时,处理可在另一处理器/机器上继续。如果一个处理器或机器故障,处理可 以最小中断在另一处理器或机器上恢复。由于此处所描述的技术不要求操作系统的协作, 因此在一些实施例中,处理可在运行不同操作系统的处理器/机器上继续。如果适当的版 本被编译在新的体系结构上且检查点的文件格式是可跨体系结构移动的,则程序可运行在 不同操作系统上。
[0054] 图5显示了具有多个微处理器502和503的计算设备501的示例。当崩溃或中断 执行的其它故障发生时,整个程序或程序线程可运行在微处理器502上。使用此处所描述 的技术,程序或程序线程可使用表示程序的执行的状态的存储在永久存储器504中的数据 在微处理器503上继续程序的执行。
[0055] 图6显示包括具有微处理器602的计算设备601和具有微处理器604的计算设备 603的计算环境的示例。当崩溃或中断执行的其它故障发生时,程序或程序线程可运行在 微处理器602上。使用此处所描述的技术,程序或程序线程可在设备603的微处理器604 上继续程序的执行。设备601和603可通过任何适当的通信连接来连接。设备501、601和 603可以是任何适当的计算设备,诸如通用计算机或者例如此处所描述的其它设备。
[0056] 至此描述了本发明的至少一个实施例的若干方面,可以理解,本领域的技术人员 可容易地想到各种更改、修改和改进。
[0057] 这样的更改、修改和改进旨在是本发明的一部分,且旨在处于本发明的精神和范 围内。从而,上述描述和附图仅用作示例。
[0058] 可以多种方式中的任一种来实现本发明的上述实施例。例如,可使用硬件、软件或 其组合来实现各实施例。当使用软件实现时,该软件代码可在无论是在单个计算机中提供 的还是在多个计算机之间分布的任何合适的处理器或处理器集合上执行。该处理器可被实 现为集成电路,集成电路组件中具有一个或多个处理器。然而,可使用电路按照任何适合的 方式来实现处理器。
[0059] 此外,应当理解,计算机可以用多种形式中的任一种来具体化,如机架式计算机、 台式计算机、膝上型计算机、或平板计算机。此外,计算机可以具体化在通常不被认为是计 算机但具有合适的处理能力的设备中,包括个人数字助理(PDA)、智能电话、或任何其他适 合的便携式或固定电子设备。
[0060] 同样,计算机可以具有一个或多个输入和输出设备。这些设备主要可用于呈现用 户界面。可用于提供用户界面的输出设备的示例包括用于可视地呈现输出的打印机或显示 屏和用于可听地呈现输出的扬声器或其他声音生成设备。可用于用户界面的输入设备的示 例包括键盘和诸如鼠标、触摸板和数字化输入板等定点设备。作为另一示例,计算机可以通 过语音识别或以其他可听格式来接收输入信息。
[0061] 这些计算机可以通过任何合适形式的一个或多个网络来互连,包括作为局域网或 广域网,如企业网络或因特网。这些网络可以基于任何合适的技术并可以根据任何合适的 协议来操作,并且可以包括无线网络、有线网络或光纤网络。
[0062]而且,此处略述的各种方法或过程可被编码为可在采用各种操作系统或平台中任 何一种的一个或多个处理器上执行的软件。此外,这样的软件可使用多种合适的程序设计 语言和/或程序设计或脚本工具中的任何一种来编写,而且它们还可被编译为可执行机器 语言代码或在框架或虚拟机上执行的中间代码。
[0063]就此,本发明可被具体化为用一个或多个程序编码的一个计算机可读存储介质 (或多个计算机可读介质)(例如,计算机存储器、一个或多个软盘、紧致盘(CD)、光盘、数字 视频盘(DVD)、磁带、闪存、现场可编程门阵列或其他半导体器件中的电路配置、或其他非瞬 态的有形计算机存储介质),当这些程序在一个或多个计算机或其他处理器上执行时,它们 执行实现本发明的上述各个实施例的方法。计算机可读存储介质或媒质可以是可转移的, 使得其上存储的一个或多个程序可被加载到一个或多个不同的计算机或其它处理器上以 便实现本发明上述的各个方面。如此处所使用的,术语”非瞬态计算机可读存储介质”只包 含可被认为是产品(即,制品)或机器的计算机可读介质。可替代地或附加地,本发明可以 体现为除了计算机可读存储介质以外的计算机可读截止,比如传播信号。
[0064] 此处以一般的意义使用术语”程序”或”软件”来指可被用来对计算机或其他处理 器编程以实现本发明上述的各个方面的任何类型的计算机代码或计算机可执行指令集。另 夕卜,应当理解,根据本实施例的一个方面,当被执行时实现本发明的方法的一个或多个计算 机程序不必驻留在单个计算机或处理器上,而是可以按模块化的方式分布在多个不同的计 算机或处理器之间以实现本发明的各方面。
[0065] 计算机可执行指令可以具有可由一个或多个计算机或其他设备执行的各种形式, 诸如程序模块。一般而言,程序模块包括执行特定任务或实现特定抽象数据类型的例程、程 序、对象、组件、数据结构等。通常,程序模块的功能可以按需在多个实施例中进行组合或分 布。
[0066] 本发明的各个方面可单独、组合或以未在前述实施例中特别讨论的各种安排来使 用,从而并不将其应用限于前述描述中所述或附图形中所示的组件的细节和安排。例如,可 使用任何方式将一个实施例中描述的各方面与其他实施例中描述的各方面组合。
[0067] 同样,本发明可被具体化为方法,其示例已经提供。作为该方法的一部分所执行的 动作可以按任何适合的方式来排序。因此,可以构建各个实施例,其中各动作以与所示的次 序所不同的次序执行,不同的次序可包括同时执行某些动作,即使这些动作在各说明性实 施例中被示为顺序动作。
[0068] 在权利要求书中使用诸如”第一”、”第二”、”第三”等序数词来修饰权利要求元素 本身并不意味着一个权利要求元素较之另一个权利要求元素的优先级、先后次序或顺序、 或者方法的各动作执行的时间顺序,而仅用作将具有某一名字的一个权利要求元素与(若 不是使用序数词则)具有同一名字的另一元素区分开的标签以区分各权利要求元素。
[0069] 同样,此处所使用的短语和术语是出于描述的目的而不应被认为是限制。此处对 “包括”、”包含”、或”具有”、”含有”、”涉及”及其变型的使用旨在包括其后所列的项目及其 等效物以及其他项目。