计算机工程
COMPUTER ENGINEERING 
1999年 第25卷 第5期 Vol.25 No.5 1999



基于部件设计的可靠性研究
云晓春 方滨兴
摘要 研究基于部件设计的可靠性问题.首先提出一个基于部件设计的模型:如何抽象地描述一个部件?如何利用已破的部件构造新的部件?如何在给定部件实现的情况下,静态地验证部件的正确性?然后讲座在部件实现不可知的情况下,如何利用包裹(wrapper)技术和虚拟部件行为模式动态地检测并保证部件运行的正确性.
关键词 基于部件设计 形式语义 可靠性.
Research on the Reliability of Component Based Design
Yun Xiaochun Fang Binxing
(Computer Department,Harbin Insititute of Technology Harbin 150001)
[Abstract] Inthis paper,we study the problems of reliability.We firstlyu present a model of component bases design:How to describe a component abstractly?How to construct a new component in terms of sub-conponents?How to verify the correcrtness of a component using warpper and virtral component behaviour pattern.
[Key words] Component based design; Formal semantica; Reliability
　　在开发大型商业软件时通常会遇到费用昂贵、耗时、难于测试、维护和更新等问题，人们通常把这一系列严重问题统称为 " 软件危机 " 。基于部件设计的思想正是针对这些问题而提出的。它的基本策略是：利用可重用、预测试且可独立更新的部件来装配软件。具体地讲：在软件开发过程中，软件工程师不再从基本的代码写起，而是将具有某些特定功能的部件组合在一起以构成一个复杂的系统。在这里，部件功能的获取不是通过考察其内部细节，而是通过观察部件接口的抽象描述获知 [1] 。基于部件的设计是一个基于对象的软件运动。它提出了这样一个一般性问题：当应用元素是由不同厂商使用不同语言、工具及计算平台所构造的，如何利用它们来设计系统的？这种软件开发方式的目标是使得最终用户和开发者能够像视听电子元件的生产、消费者那样享受到同样高层次的即插即用的应用互操作性。时至今日，利用已存部件构造软件已引起愈来愈多的重视。许多机构正在进行部件重用工程的研究，大量的重用工具正在应用和研制中[2] 。
　　基于部件设计可被看作一个渐次积累的过程：当一个软件由一些子部件构造成功之后，它同时又可作为一个新的部件放入部件库中被其它软件所重用 ( 如图 1) 。 

图1 基于部件设计过程
　　本文中，我们主要关注如下两个问题： 
　　(1)  基于部件设计的模型是什么？当利用子部件构造部件时，如何验证这种设计的正确性？ 
　　(2)  当部件的实现不可知时，如何保证部件的正确执行？ 
1  基于部件设计的模型 
　　一个部件的本质是什么？直觉上，将部件看作一个计算单元，它具有其自身的内部状态并提供一组操作来对这个状态读出和写入。部件的状态是不可见的，它只能通过调用部件中的操作才能访问到。在基于部件设计的模型中，规定任何一个部件都是由若干子部件按一定的控制结构构造而成。 
　　由于基于部件的设计需要一种机制来保障子部件之间可以相互合作并能够同时开发。为此，通常的做法是将每个部件的描述分成两个层次： 
　　・接口：抽象地描述每个部件的外部行为，并以此作为其它部件的使用依据。 
　　・实现：接口中描述的具体实现。 
1.1  接口 
　　一个部件的抽象描述包括语法级和语义级两个层次。语法级描述刻画了怎样调用一个部件的操作；而语义级描述则刻画了部件中操作的行为特性。对于部件的语义，主要关心部件的初始特性以及一个操作的执行所导致的部件特性的变化。使用一阶逻辑 (first-order logic) 语言 [4] 来描述部件的特性： 
　　定义 1    一个特性 P 指的是对应于读操作的一个命题公式。它或者是一个布尔真值 T ，或者是一个原子特性 p ，或者是一个反特性P ，或者是一个合取特性 P1∧P2 ，或者是一个析取特性 P1∨P2 ，或者是一个暗指特性 P1= 》P2 。即： 

　　其中原子特性指的是对应于读操作的一个关系表达式。例如：假设 X 、 Y 、 R 是某个部件的读操作，则类似于 X=1 ， R<Y ， X=R+Y 
　　这样的表达式都是原子特性。 
　　一个部件的初始特性指定了它的初始状态要求。同时使用一个特性对来定义部件中每个写操作的语义，其含义是：如果相应写操作在满足第一个特性 ( 预条件 ) 的任意状态下执行，则其执行完毕后第二个特性 ( 后条件 ) 一定满足。 
　　这样，可以给出部件接口的模型：一个部件的接口描述包括一个初始特性，一组读写操作的名字及其语法描述，另外对于每个写操作还提供了一个特性对，用于描述该操作执行前后的行为约束。 
1.2 实现 
　　在基于部件设计中，将部件实现时所用到的子部件分为全局子部件和局部子部件两类，其中前者可被部件中的每个操作所访问，它存在于部件的整个生命周期；而后者则只能被某个特定操作所访问，它只在相应操作执行时才创建，并在操作执行结束后即撤销。下面提出一个简单的部件实现模型： 
　　一个部件的实现包含以下两部分： (1)  其所有子部件的名字和接口信息； (2)  根据子部件的操作对读写操作所进行的定义。 
　　在这里 ,  强调子部件的接口是其在部件中被重用的唯一依据，即子部件的实现中所描述的语法和语义信息同其接口的抽象描述是一致的。这样可以给出部件的实现模型：   部件中的每个读操作的实现对应于一个由子部件的读操作所构成的程序 ,  而每个写操作的实现对应于一个由子部件的读或写操作所构成的程序。 
　　那么，什么是一个程序？为此定义一个简单的程序模型：一个程序或者是一个原子程序；或者是程序 P1和 P2的顺序执行；或者是以特性S为测试条件的程序P的选择执行；或者是以特性S为测试条件的程序P的循环执行。其中原子程序则对应于一个调用操作c.op,其语义是调用部件c中的操作op。假设 P、P1、P2程序，而S是部件中的一个特性，则上述程序模型可形式化地描述如下： 
P≡c.op|P1;P2|if S then P1|while S do P1
1.3  语义一致性验证 
　　一个部件的接口描述同其具体实现相互分离引发了一个潜在的问题 :  该部件的实现是否正确地满足了其接口中所给定的抽象描述 ?  为解决这种正确性问题 ,  应用 Hoare 逻辑 [4] 作为进行证明的基本手段。 Hoare 逻辑是一种对程序进行推理的理论。它讨论了程序正确性证明的问题并提出了一种独立的公理方法来获得程序的稳定性。 
　　由上节所刻画的部件实现模型可知 ,  部件中所有操作的实现都是由其子部件中的操作合成的，故而部件的语义可由这些子操作的合成语义所代表。基于此 ,  提出相应的验证策略：首先根据子部件接口中所给出的语义说明，应用 Hoare 逻辑所给出的规则计算出部件的初始特性以及每个写操作的预条件和后条件，然后对照给定的部件接口说明以及一组验证条件，判断部件实现的正确性。 
　　可使用下面的算法计算一个部件的实现所代表的语义： 
　　该部件的初始特性等价于其所有全局子部件的初始特性所构成的合取特性；由于子部件接口中给出了每个写操作的语义信息，因此对于任一个原子程序 c.op ，可假定其对应预条件和后条件为 (p,q) ，根据这一假设，对于部件中每个写操作，若其对应的程序为 C ，则该操作的预条件和后条件可递归地计算如下
： 
　　根据上面的算法，我们可给出部件正确性的定义： 
　　定义 2 对于任一个部件，假设 P1 是其接口中所给定的初始特性，且对于每个写操作 wi 其对应的预条件和后条件分别为 Pi1 和 Qi1 ；应用上面的算法计算该部件实现的语义，假设所计算出的初始特性为 P2 ，且对于每个写操作 wi 计算其预条件和后条件，结果为 Pi2 和 Qi2 ；则仅当下列条件成立时，该部件在逻辑上一定是正确的： 
　　(1)  下列特性恒为真：P1=》P2, Pi1=》Pi2, Qi2=》Qi1; 
　　(2)  对于部件实现中任一个写操作wi，假设其对应的程序为C，则下列特性恒为真：
　
　　显然，定义 2 是一个充分条件 ,  即满足定义 2 的部件一定是正确的，但反之并不成立。定义 2 的意义就在于它为开发一个正确的部件提供了指南，虽然依据这一定义开发部件受到一定约束，但毕竟对于一些安全性要求很高的领域 ( 如航空、航天 ) ，知道了什么样的部件实现一定是正确的。在这里，还需强调一点：总是假设子部件是正确的。在这一假设之上，一个逻辑上正确的部件实现才是真正正确的。那么，在只给定子部件接口信息的情况下，如何验证子部件的正确性？ 
2 部件的容错运行 
　　由于通常情况下，部件重用时，其具体实现细节是不可见的。因此，无法使用 Hoare  逻辑静态地验证部件的正确性。下面将提出一种运行时技术使其能够在未知部件实现的情况下检测部件的运行同其接口说明是否一致。 
　　由于在部件的接口中形式化地描述了部件的语义信息，因此基本策略是构造一个生成器 (generator) ，其功能是利用部件接口中的形式语义，自动生成一个包裹部件，该部件接收来自外部的调用要求，监视被测试部件的运行并在出现运行时错误时进行相应处理。 
　　一个包裹部件包含两个子部件：被监测部件和信号灯部件 (semaphore) 。信号灯部件用于在监测到运行时错误时设置出错标志并在操作执行完毕后设置结束标志，它提供了 4 个操作： 
　　(1)fault ：读操作 -- 表明错误标志是否置位； 
　　(2)setfault ：写操作 -- 对错误标志进行置位； 
　　(3)over ：读操作 -- 表明操作是否结束；
　　(4)setover ：写操作 -- 对结束标志进行置位。 
　　作为额外的一层设计，包裹部件根据信号灯子部件中的 fault 操作和 over 操作提供了两个读操作 w_fault 和 w_over 用于表明被监测部件是否出错以及前一个操作是否结束，这里假设对每个部件操作的调用是单线程的；同时该包裹部件提供了一组与被测部件相同的读操作用于观察被测部件的状态特性；至于包裹部件中的写操作集合则同被测部件的写操作集合相同，但其语义有所变化：包裹部件接收到写操作调用要求后，首先测试对应操作的预条件，如果不满足则挂起该调用，否则执行相应的部件操作；操作执行完毕后，对结束标志置位并测试该操作的后条件，如果不满足则将信号灯错误标志置位。图 2 给出了包裹部件的执行算法。 

图2 包裹部件执行算法
　　包裹部件的技术提供了检测部件运行时错误的手段，那么当检测到部件错误时如何在不修改源程序的前提下动态地对部件进行替换？为此提出一个新的部件行为模式：虚拟部件，期望在设计中系统地使用这一模式以保证部件的容错运行。 
　　类似于实际部件的设计，虚拟部件也提供了一个单一的接口描述；所不同的在于，虚拟部件模式中，部件实现不再是单一的，而是允许在设计中将满足该接口描述的多个部件聚集起来构成一个部件组，同时为该部件组构造一个代理部件作为连接客户端同部件组的桥梁。当客户程序调用虚拟部件的接口中所给出的操作时，它不再直接同具体部件打交道，而是向相应的代理部件发出调用要求，由代理在部件组中动态地选择可靠部件，并在发现部件运行时错误时，自动地对部件进行替换，从而实现对客户端透明的部件容错运行。图 3 给出了虚拟部件的结构，这里假定部件组中的每个部件都是一个包裹部件，具有自检错的能力。 

图3 虚拟部件结构
　　在虚拟部件模式中，其可靠性是通过代理部件动态地选择部件组中的正确部件完成的。在部件组中采用文献 [3] 所提出的 coordinator-cohort 计算方案，即将部件组中的一个成员部件设定为协调部件 (coordinator) ，用来执行客户端所要求的操作；并把部件组中的其它的部件成员称为随从部件 (cohort) ，这些部件是被动的，它们不执行客户端的调用操作。如果协调部件发生错误，则选取一个随从部件作为新的协调部件。另外，随从部件需要周期性地根据协调部件的内部状态更新其自身状态，以用作备份目的。基于这一计算方案，图 4 中描述了代理部件执行动态调用的算法。 

图4 代理部件动态调用算法
　　在虚拟部件中，为实现部件之间的状态传送，我们约定代理部件以及部件组中的每个成员都必须包含两个操作： get_state 和 set_state ，这样，在每次动态调用的结尾，代理部件就可以通过 get_state 从协调部件中读取其内部状态，然后调用每个随从部件的 set_state 操作，对其状态进行更新。 
　　显然，如果一个部件组有 n 个部件成员，则客户端的调用要求在至多 n-1 个部件成员出错的情况下仍能可靠地完成。对比单部件运行的模式，这一行为模式能够获得更高的可靠性。 
3 结论 
　　本文给出了一个基于部件设计的简单模型，并在这一模型的基础上给出了进行正确性验证的策略。我们坚信这些内容对于提高基于部件设计的可靠性具有积极的指导意义。  
作者简介:云晓春,男,28岁,博士生,主要从事基于部件设计技术及并行计算技术研究
作者单位:哈尔滨工业大学计算机系 哈尔滨150001
参考文献 
1　Adler R M.Emerging Standards for Component Software.IEEE Computer，1995，(3)：68 
2　Zaremsk A M,Wing J M.Signature Matching: A Key to Reuse. ACM Transactions on Software Engineering and Methodology，1995，4(2)：146 
3　Maffeis S.Run-time Support for Object-oriented Distributed  
Programming.Ph.D Dissertation in University of Zurich，1995-02：137
4　Gordon M J C.Programming Language Theory and Its Implemen-tation.Prentice Hall，1988：13-29 
收稿日期:1998-06-19
