摘要:由于構件對象可以動態加載#65380;動態聚合,同時也能動態卸載#65380;動態拆離,使得軟件可以運行在計算能力或存儲能力較弱的設備上。通過基于AOP及Elastos操作系統的平等計算模型的實現,在很大程度上提高了應用的終端適應能力,從而為開發更大的移動應用提供了技術支持。
關鍵詞:面向方面的編程; Elastos; CAR; 構件; 平等計算; 動態聚合
中圖分類號:TP316文獻標志碼:A
文章編號:1001-3695(2008)02-0420-03
0引言
面向方面的編程(aspect oriented programming,AOP)是在面向對象編程的基礎上引入方面的概念的一種編程方法。在目前的面向對象的編程模式中,僅僅用類的思想來分析和實現軟件系統,不能有效地表示軟件系統的關注點。而AOP是有效分離關注點的新型編程方法[1]。
本文基于CAR構件系統,提出了AOP的動態聚合模型及其實現,并由此實現了平等計算模型。與其他系統的靜態聚合方法相比,動態聚合所具有的隨時聚合#65380;隨時拆卸的特點更加有效地提高了系統的適應性和重用性。
1Elastos中的動態構件管理——平等計算模型
基于永久在線網絡(如TD-SCDMA網#65380;WiFi網)支持的各種數字媒體的應用程序可以提供一些新的技術特性:如按需計算#65380;滾動下載和點擊運行等。應用程序可以運行在數字媒體終端上(本地運行),也可以運行在遠程服務器上(遠地運行)。應用程序根據用戶的請求動態地加載和聚合運行構件,用戶不必關心軟件安裝#65380;網絡配置#65380;維護備份等技術細節。
Elastos設計并實現了構件的平等計算模型,這個模型是實現按需加載#65380;按需計算和點擊運行的理論基礎,是3G及B3G數據應用的基本技術特征。這個模型的基礎在于構件的自描述能力,每個構件都能通過統一的接口查詢出它提供的對外服務及需要其他構件提供的服務。構件不再需要依照依存關系全部加載到內存中來才開始計算,而是由Elastos操作系統管理所有對外引用。當被引用的構件不在內存時,將為其建立運行環境(可能加載到本地內存,也可能變成遠地資源引用)。這時的構件可能是一個字體文件#65380;一個圖片等。通過將一件大事分解為許多小事,將減小計算資源并發需求,是計算的真正網絡化[2]。
傳統的計算模型為軟件構件調度計算模型,如圖1所示。圖1中,A構件引用了B構件和C構件。無論在某一時刻A構件是否對B構件或C構件實施了真正的引用,B構件和C構件都是處于S構件(一般是操作系統)的管理之中;一旦應用系統(A#65380;B#65380;C三個構件組成)開始運行,管理構件S將不再介入應用系統各組成部件之間的關系。
本文所提出的軟件構件平等計算模型,從計算理論上實現了按需計算,如圖2所示。圖2中,A構件引用了B構件和C構件。但在A構件未對C構件實施真正引用時,C構件是處于自由態的,即可能還不在整個計算環境中。每個構件獨立地受到運行環境的管理,互相之間的數據交換#65380;計算引用等也受運行環境的控制。
軟件構件平等計算模型已經在本文的基于構件的Elastos操作系統中實現。在這個模型的支持下,考查一個計算的復雜度時,不再看其本身邏輯是否復雜,更看重的是在某一個時刻參與計算的構件的參與情況,降低計算對硬件的要求。
實現軟件構件平等計算模型有很多種策略,如改造傳統的模塊加載機制#65380;利用動態聚合實現構件動態管理等。根據硬件#65380;網絡#65380;人機交互體驗等環境的不同,可以選用不同的策略。
2利用AOP機制實現運行時平等計算模型
平等計算可以在操作系統的模塊管理器(module manage)中通過對模塊的加載過程的改造實現。考慮到系統的靈活性和加載模塊的可管理性,筆者通過一個標準構件管理構件(一個aspect構件)和CAR構件實現對CAR構件的管理,并通過Elastos支持的AOP機制完成整個計算過程的支持。
2.1基于CAR的AOP機制
CAR構件主要由其所定義的接口#65380;構件類及其包含的方法和相關元數據組成。CAR構件技術規定了一組構件間相互調用的標準,使得二進制構件能夠自描述#65380;能夠在運行時動態鏈接。
基于CAR的AOP機制使用戶能夠在完全不用修改源代碼的情況下簡單而方便地動態聚合兩個或多個CAR構件類,從而生成一個具有兩個或多個CAR構件類所有接口實現的新構件類。CAR的AOP技術由方面#65380;動態聚合(dynamic aggregation)和上下文環境 (context)組成[3]。
Aspect對象是實現動態聚合的必要條件,動態聚合是上下文環境實現的基礎[4]。Aspect是一種特殊的構件類實現,aspect對象就是實現了IAspect接口的構件對象。如果aspect對象被其他構件對象聚合,對IObject的方法調用則會被委托給外面的聚合對象上,外部對象保存aspect對象的IAspect的接口指針,用于aspect對象的真正QueryInterface。
Aspect對象在聚合情況下的接口示意圖如圖3所示。
Elastos還支持一個對象聚合多個aspect對象,也就是多面聚合。本文在完成多面聚合時,其實現就是創建多個aspect對象,多次調用EzAggregate方法使一個對象聚合多個aspect對象。這樣就為平等計算所需的動態加載提供了實現的基礎。
2.2CAR的aspect對象的動態聚合
動態聚合是通過IObject的aggregate方法來完成的,因此構件編寫者定義的每個構件對象都具有聚合其他aspect對象的能力。例如一個構件對象A(構件類為CA)和一個aspect對象B(構件類為CB),對于構件A的編寫者來說,在構件對象A中如果要聚合aspect對象B,只要通過如下過程就可完成聚合任務:
a)創建aspect對象B,如:
ec=EzCreateObject(CLSID_CB,CTX_SAME_DOMAIN,IID_IObject,pObj);
b)調用CAR構件庫提供的聚合函數EzAggregate:
ec=EzAggregate((IObject *)this, pObj);
pObj->Release();
EzAggregate函數調用成功后,那么對象B中保存了外部對象A的指針,對象A則保存了內部對象B的IAspect指針,同時內部對象B的引用計數也轉嫁到了外部對象A上。
EzAggregate函數聲明如下:
CARAPI EzAggregate(
/*[in]*/ POBJECT pAggregator,
/*[in]*/ POBJECT pAspect)
其中:pAggregator為外部對象指針;pAspect為內部對象(aspect對象指針)。而實際上EzAggregate的實現就是調用aggregate方法:
CARAPI EzAggregate(
/* [in] */ POBJECT pAggregator,
/* [in] */ POBJECT pAspect){
return pAspect->aggregate(AggrType_Aggregate, pAggregator);
}
聚合時也可直接像上面那樣調用aggregate方面來完成聚合過程,如:
ec=pObj->aggregate(AggrType_Aggregate, (IObject *)this);
//AggrType_Aggregate指定aggregate方法是聚合行為
Aggregate方法在聚合時是引發了一系列的調用來完成聚合過程的,這個過程可以簡單地表示如下(為了簡便,本文將外部對象指針用pOuter表示,pAspect表示IAspect指針):
a)外部對象A調用
pAspect->aggregate(AggrType_Aggregate, pAggregator);
b)Aspect對象B及時反調外部對象的aggregate方法
pOuter->aggregate(AggrType_AspectAttach,pAspect);
c)外部對象保存aspect對象指針
d)Aspect對象保存外部對象指針并將所有的引用計數全部轉嫁到外部對象,聚合過程完成。
Aggregate過程是在CA里調用了CB的aggregate方法,其AggregateType為AggrType_Aggregate,然后在內部對象CB中又及時反調了外部對象的aggregate方法,這時的AggregateType為AggrType_AspectAttach,這個過程可稱之為attach過程。Attach過程保存了aspect對象的IAspect接口指針,在多面聚合的情況下,attach過程就是將一個aspect對象添加到聚合鏈中。
通過上面的聚合過程,外部對象就有了指向aspect對象的指針(m_pAspect),被聚合的aspect對象就有了指向外部對象的指針(m_pOuter)。聚合后的兩個對象的狀態如圖4所示。
3構件動態加載的管理
為了實現構件的動態加載,必須設計一個稱之為偽殘根的接口對象,用于保存引用虛表的信息以及被聚合對象的元數據,實現動態加載時的管理[5]。偽殘根接口IStub的基本定義如下:
interface IStub : public IObject {
virtual CARAPI_(void) invoke(
/* [in] */ void *pvData,
/* [in] */ UINT uSize)=0;
virtual CARAPI getOid(
/* [out] */ OID *pOid)=0;
virtual CARAPI getClsid(
/* [out] */ CLSID *pClsid)=0;
virtual CARAPI interfaceIndex(
/* [in] */ IObject *pObj,
/* [out] */ UINT *puIndex)=0;
virtual CARAPI getClassEntry(
/* [out] */ UINT *pClassEntry)=0;
};
//引用虛表的各元素定義
typedef struct IStubVtbl
{
ECODE (CARAPICALLTYPE *queryInterface )(
IStub * this,
/* [in] */ RIID riid,
/* [iid_is][out] */ POBJECT *ppObj);
…//其他元素定義;
} IStubVtbl;
//虛表定義
interface IStub {
CONST_VTBL struct IStubVtbl *v;
};
偽殘根接口中儲存的信息如表1所示。
當一個構件模塊要動態加載另一個構件模塊時,首先調用queryInterface方法,查看所需要的構件模塊是否已經聚合到本構件中。如果已加載,則返回此構件模塊的接口指針,并增加被加載構件的引用計數;否則,就為即將要加載的構件對象作以下準備。如果系統資源不足,則請求Elastos清理一下環境;然后獲取要加載的構件對象的元數據;創建構件對象的偽殘根(IStub),并在每個接口引用的地方引入計時;動態聚合構件并返回構件的接口指針。
引入計時的目的是為了管理被加載構件模塊的生命周期,當某些構件不再使用時,可以動態卸載。如果計時超過了預訂的時間,則先解除有關構件模塊的聚合關系,然后卸載此構件模塊。
構件在動態加載和卸載的管理邏輯的偽代碼如下所示:
static time_t tm=0;
computeOnDemandAspect的queryInterface()
{
if(我的實體已經加載) {
返回實體的接口指針
實體計時數據tm=當前時間
return;
}
if(所用資源>=臨界狀態 )
//請求Elastos清理一下環境
computeOnDemandFlush()
}
//獲取構件的元數據
//創建構件對象的偽殘根,在每個接口引用的地方引入計時
//動態聚合構件并返回構件的接口指針
}
//卸載
computeOnDemandFlush()
{
if(timeLeaved>PREDEFINED_TIME_PEROID)
//去除有關構件的聚合
/*如果相應模塊真的不需要了,利用Elastos自身的模塊管理機制把模塊卸載*/
}
//改造系統定時器事件,定期清理環境
5結束語
本文基于AOP中的aspect思想,結合CAR構件技術的動態聚合實現了動態加載,進而實現了平等計算模型。與其他系統的靜態聚合方法相比,動態聚合所具有的隨時聚合#65380;隨時拆卸的特點更有效地提高了系統的適應性和重用性。
在現在各種手持終端和移動設備越來越便攜化#65380;越來越智能化的應用背景下,具有動態加載和動態聚合特點的平等計算模型將是解決各種終端計算能力相對有限而計算需求又高的問題的較好計算模型。
參考文獻:
[1]ERL T. Service-oriented architecture(SOA): concepts, technology and design[M]. Upper Saddle River: Prentice Hall PTR, 2005:167-378.
[2]GRUNDY J. Aspect-oriented requirements engineering for component-based software systems[C]//Proc of the 4th International Symposium on Requerements Engineering. Limerick, Ireland:[s.n.], 1999.
[3]郭強,范典,陳榕,等.CAR中基于上下文AOP機制的實現[J].計算機應用研究,2005,22(10):220-222.
[4]上海科泰世紀技術有限公司.Elastos資料大全[EB/OL].[2006-10].http://www.koretide.com.cn.
[5]上??铺┦兰o技術有限公司.CAR構件技術與編程模型[EB/OL].[2006-10].http://www.koretide.com.cn.
“本文中所涉及到的圖表、注解、公式等內容請以PDF格式閱讀原文”