查的副作用。轻量进程快照,此处也被称为进程快照,是有效率地被创建的进程的副本,而无需创建进程的执行或存储器的全部轨迹。通常,操作系统在其虚拟存储器模型顶上实现快照机制,并使用共享存储器页面和写入时复制技术,避免创建进程的完整的副本。相反,写入时复制允许操作系统快速地将原始进程的整个地址空间的实际页面映射到第二进程快照。在创建快照之后,向任意进程的任何存储器写入导致为执行写入的进程创建该对应的存储器页面的副本。如此,为存储器写入实现了副作用隔离。
[0028]针对轻量进程快照使用基于func-eval的检查模型的调试程序应用下列算法:
[0029]首先,当调试程序进入中断模式时,调试程序要求操作系统创建原始进程的新的轻量快照。此快照必须准确地反映原始进程,包括通过写入时复制,映射被调试程序进程存储器,复制进程内的线程,复制进程内的任何句柄,以及在进程中加载相同模块。调试程序必须能够执行进程快照内的代码,以便执行func-eval。
[0030]其次,当调试程序需要执行func-eval时,它在轻量进程快照进程内,而非在原始进程内这么做。这提供了与针对原始进程运行func-eval等同的结果,因为快照是原始进程的克隆,因此,在进程快照内执行func-eval将与在原始被调试程序进程内执行func-eval 等同。
[0031]值得注意的是,取决于操作系统支持的复制的级别,使用此模型,可能不能隔离某些副作用。例如,将实际产生对外部实体的副作用,诸如在func-eval期间的文件写入。此夕卜,如果操作系统不能够复制全部进程,对未被复制的任何事物(诸如共享的内核对象)的副作用,可能会实际影响原始进程。
[0032]再其次,当在快照进程内执行func-eval时,调试程序可以选择错过在真正的被调试程序进程中的所有线程。这允许真正的被调试程序进程中的所有线程执行。这降低了在被调试程序进程跨分布式环境(诸如COM套间边界)作出调用或允许可能被其他线程持有的锁被释放的情况下死锁该被调试程序进程的可能性。如果调试程序执行允许线程错过的评估,则调试程序将需要在评估完成之后创建原始进程的新的快照。这是必需的,因为进程快照的状态在评估之后已显著变化,并可能不再是当前真正的被调试程序进程的准确的
[0033]第四,当进程快照中的func-eval发生错误时一例如,由于死锁的功能评估,它超时,或来自开发人员希望撤消的以前的评估有明显的副作用一调试程序可以简单地删除旧快照并创建新的快照。新进程快照再次是原始进程的复制。
[0034]在某些情况下,调试程序将知道自动地创建新进程快照。例如,调试程序在处于运行模式之后进入中断模式时将总是需要创建新的进程快照。这是需要的,因为被调试程序状态将很可能在中断状态之间急剧地变化。然而,有时,用户可能需要强制创建新的快照。这可以通过调试程序用户界面启用。
[0035]图1示出了通过轻量进程快照的历史调试。调试程序进程101被用于调试被调试程序进程102。调试程序进程101具有允许用户分析被调试程序进程的组件的用户界面。例如,用户界面可以提供示出调用堆栈103、模块104、线程105,以及变量检查106的窗口。被调试程序进程102包括,例如,线程107、模块108,以及虚拟存储器页面表109。虚拟存储器109指向由操作系统的虚拟存储器管理器111管理的物理存储器页面110。
[0036]在调试会话期间,创建轻量进程快照112和113。这些是在特定的时间取得的被调试程序进程102的快照。快照112、113可以由用户手动地启动,或当观察到特定事件或触发器时或以某些间隔,调试程序101可以自动地生成快照112、113。
[0037]快照112包括线程表114和模块表115,它们是在快照112被创建时的时间(Tl)的调试程序101的内部表的副本。虚拟存储器页面表116指向在当快照112被创建的时间Tl时正在使用的物理存储器页面110。最初,虚拟存储器109和虚拟存储器116将等同;然而,随着被调试程序进程继续运行,虚拟存储器109将随着其页面表指向更新的存储器位置I1而变化。
[0038]类似地,在另一个时间(T2),响应于用户选择或由调试程序进程101观察到的事件或触发器的发生,创建进程快照113。快照113包括在当快照被创建的时间T2时的线程表117和模块表118的副本,以及当时的虚拟存储器页面表119的副本。
[0039]快照112、113允许调试程序进程101或用户回头看在快照112、113被创建的时间(Tl,T2)时被调试程序进程102看来像什么,尽管被调试程序进程102在此期间变化。此夕卜,调试程序进程还可以比较被调试程序进程102和/或进程快照112、113之间的状态,以生成在不同的时间的不同的进程状态之间的差异,以便用户可以看出进程什么部分变化以及如何变化。
[0040]在其他实施例中,可以创建快照112,并且原始被调试程序进程102可以被允许没有干扰地运行。然后,可以针对进程快照112进行测试,以观察对进程有何影响。如果进程快照112失败或由于测试而有其他问题,那么,那些问题将不会影响真正的运行中的进程102。
[0041]图2示出了根据一实施例的轻量进程快照。原始进程201包括指向存储在物理存储器203中的数据的页面表202。例如,进程201可以将变量X存储在指向实际存储了变量X的值的物理存储器位置205的页面表条目204中。
[0042]当从原始进程201创建进程快照206时,作为快照页面表207,复制原始页面表202。快照页面表207的内容与原始页面表202的内容相同,因为它在创建快照时就存在。例如,在进程快照206中,变量X指向快照页面表207 (与原始页面表202 —样,指向存储了变量X的值的物理存储器位置205)中的条目208。
[0043]原始进程201可以在创建快照之后继续运行。原始进程可以为变量X生成新的值,该新的值再次存储在原始页面表202的条目204中。然而,变量X的新的值存储在物理存储器203中的新的位置209。相应地,原始页面表202被更新,以指向物理存储器位置209,但是,快照页面表207维护其快照状态,并指向变量X的原始值仍驻留在那里的存储器位置205。
[0044]快照机制可以允许破坏性较小的调试检查。通常,当在调试进程时在中断模式下时,被调试程序进程被操作系统停止。这意味着,被调试程序进程内的代码不执行。这对于检测被调试程序状态是理想的,因为当进程被停止时该状态不能变化。然而,在某些情况下,停止进程会导致死锁或其他系统不稳定性。例如,当在其他进程之间共享被调试程序进程时,其他进程可能企图与处于中断模式中的共享的被调试程序进程进行通信。在最佳情况下,这会在其他进程中导致延迟,在最坏的情况下,导致死锁、进程损坏,以及不稳定性。轻量快照模型通过允许调试程序检测共享进程的轻量进程快照,而并非真正的进程,以在这样的情况下启用调试。真正的进程被允许在此检查期间继续执行。
[0045]图3是示出了根据一实施例的用于执行针对轻量进程快照的功能评估的方法的流程图。在步骤301中,当调试被调试程序进程时,调试程序进入中断模式。调试程序请求操作系统创建被调试程序进程的进程快照。在步骤302中,调试程序针对进程快照执行功能评估。调试程序可以通过循环回步骤302,针对进程执行多次功能评估。如果调试程序在功能评估中标识出问题,则它移到步骤303,并丢弃进程快照。
[0046]在步骤304中,调试程序请求操作系统创建被调试程序进程的新进程快照。过程返回到步骤302,针对新进程快照,执行附加功能评估。然后,调试程序可以通过返回到步骤302,对新进程快照再次执行功能评估。可另选地,在步骤305中,调试程序可以在对新进程快照执行功能评估时错过被调试程序进程中的线程。如果功能评估失败或遇到诸如死锁之类的问题,那么,过程返回到步骤303,以丢弃死锁的进程快照,并返回到步骤304,以创建另一个新进程快照。
[0047]可以理解,图3中所示出的过程的步骤301-305可以同时和/或按顺序执行。进一步可以理解,每一步骤都可以以任何顺序执行,可以执行一次或反复地执行。
[0048]图4示出了根据一实施例的在允许真正的被调试进程继续运行的同时调试程序针对轻量进程快照执行功能评估。调试程序进程401被用于调试被调试程序进程402。调试程序进程401具有允许用户与被调试程序过程的组件进行交互并分析它们的用户界面403和调试程序引擎404。例如,用户界面可以提供示出调用堆栈、模块、线程,以及变量值的窗口。被调试程序进程502包括,例如,线程405、模块406,以及