|
|
|
| 深入BREW模块加载机制 |
编辑:rocks 审核:rocks 文章来源:歪酷博客
关键词:无 发表日期:2006-02-09 15:47:19 浏览次数:6186次 |
|
|
|
|
本文版权归原作者,中国JAVA手机网收录本文的目的是让更多人阅读到此文章。转载请注明出处为中国JAVA手机网<www.cnjm.net>
来自:http://www.cnjm.net/tech/article846.html [转载于歪酷博客] 原文:http://nicefuture.yculblog.com/post.722858.html 深入BREW模块加载机制 东方欲晓 @ 2005-06-13 20:52
深入BREW模块加载机制 作者:东方欲晓 2005-6-13 MSN:mynicefuture@hotmail.com Email: mynicefuture@126.com 转载请注明出处
JAVA手机网[www.cnjm.net] 在BREW中,module是基本的执行单位,一个module可以包含一个或多个applet,或者多个extension class。按照module处于code space(即OEM出厂时已经将module编译进image中了)还是通过下载方式(无线下载或者数据线下载)存于文件系统可以分为static和dynamic,主要包括:dynamic module(applet),static module(applet)和dynamic extension class(module)。本文将详细阐述static和dynamic module的加载过程。由于完整的module加载过程高通没有文档公开,所以以下内容是结合我阅读的相关文档以及我的日常工作而写,是我对模块加载的理解,可能有不当之处,还请指教。
JAVA手机网[www.cnjm.net] 1. Module的信息 MIF文件,这个大家都知道了。原则上来说,每个module都需要有标识自身的MIF文件,从BREW 3.1开始已经强制如此了,static module也需要有相应的MIF。而在BREW3.1之前,对于static module是没有单独的MIF文件的,但有一个AEEAppInfo的结构体来表示module的信息,里面主要包括clsid,app type等信息,每个static module都需要有一个实例化的AEEAppInfo结构体,BREW从此结构中获得必要的module信息。 2. 枚举Module信息 这一步是在BREW环境初始化的时候进行的(猜测是在AEE_init中),由于通常在开机时就初始化BREW环境,所以枚举Module信息通过在一开机就进行(进行程序跟踪结果也证实如此)。对于dynamic module,BREW通过检索各个MIF文件来获得各个module的必要信息,比如clsid等。而对于static module,由于不存在MIF文件,所以过程有所不同。每个static module的实现必须提供一个XXX_getmodinfo(),在该函数中返回特定于该module的Mod_Load()函数指针,通常形式为 XXXMod_Load,同时返回特定于该module的AEEAppInfo结构数据。所有的这些XXX_getmodinfo函数指针构成了一个staticmodinfo的数组。BREW初始化时通过检索该数组(猜测执行其中的每一个函数)来获得每个static module的相关模块信息(比如clsid)以及加载函数(我们知道,对于dynamic module, load的函数是通用的AEEMod_Load,所以应用无需再提供自己的Load函数,而static module必须提供自己的Mod_Load 函数) 3. Module加载 Module的加载是在运行时才进行的,即执行该Module的时候。对于dynamic module,加载是通过通用函数AEEMod_Load实现的,而AEEMod_Load实际是调用AEEStaticMod_New,该函数的原型为int AEEStaticMod_New(int16 nSize, IShell *pIShell, void *ph, IModule **ppMod, PFNMODCREATEINST pfnMC,PFNFREEMODDATA pfnMF),大家在AeeModGen.c中可以看到。需要说明的是,AEEMod_Load中调用该函数时,倒数第二个参数为NULL,这说明什么?我们来看看AEEStaticMod_New具体作些什么,
int AEEStaticMod_New(int16 nSize, IShell *pIShell, void *ph, IModule **ppMod, PFNMODCREATEINST pfnMC,PFNFREEMODDATA pfnMF) { AEEMod *pMe = NULL; VTBL(IModule) *modFuncs;
if (!ppMod || !pIShell) { return EFAILED;
JAVA手机网[www.cnjm.net] }
*ppMod = NULL; #ifdef AEE_SIMULATOR // IMPORTANT NOTE: g_pvtAEEStdLibEntry global variable is defined for
JAVA手机网[www.cnjm.net] // SDK ONLY! This variable should NOT BE: // // (1) overwritten // (2) USED DIRECTLY by BREW SDK users. //
JAVA手机网[www.cnjm.net] // g_pvtAEEStdLibEntry is used as an entry point to AEEStdLib, // DO NOT REMOVE the next five lines. if (!ph) { return EFAILED; } else { g_pvtAEEStdLibEntry = (AEEHelperFuncs *)ph; }
JAVA手机网[www.cnjm.net] #endif
JAVA手机网[www.cnjm.net] //Allocate memory for the AEEMod object
if (nSize < sizeof(AEEMod)) { nSize += sizeof(AEEMod);
JAVA手机网[www.cnjm.net] }
JAVA手机网[www.cnjm.net] if (NULL == (pMe = (AEEMod *)MALLOC(nSize + sizeof(IModuleVtbl)))) { return ENOMEMORY; } // Allocate the vtbl and initialize it. Note that the modules and apps // must not have any static data. Hence, we need to allocate the vtbl as // well.
modFuncs = (IModuleVtbl *)((byte *)pMe + nSize);
// Initialize individual entries in the VTBL modFuncs->AddRef = AEEMod_AddRef; modFuncs->Release = AEEMod_Release; modFuncs->CreateInstance = AEEMod_CreateInstance; modFuncs->FreeResources = AEEMod_FreeResources;
// initialize the vtable INIT_VTBL(pMe, IModule, *modFuncs);
// initialize the data members
// Store address of Module's CreateInstance function pMe->pfnModCrInst = pfnMC;
// Store Address of Module's FreeData function
JAVA手机网[www.cnjm.net] pMe->pfnModFreeData = pfnMF;
pMe->m_nRefs = 1; pMe->m_pIShell = pIShell;
// Set the pointer in the parameter *ppMod = (IModule*)pMe;
return SUCCESS;
上述代码在sdk中的AeeModGen.c可以找到,概括起来,就是在为module分配内存,并且实例化vtbl表,其中有两行代码值得注意: modFuncs->CreateInstance = AEEMod_CreateInstance; pMe->pfnModCrInst = pfnMC;
第一行是指定module的创建函数为AEEMod_CreateInstance,而第二行是指定该module具有自身特殊的创建函数,该函数即为参数pfnMC指定的函数。而在AEEMod_Load中调用AEEStaticMod_New时该参数为NULL,即所有dynamic module采用通用的createinstance 函数(该函数实际上即为AEEClsCreateInstance) 大家或许已经猜到了,对于static module,其实其自身的XXXMod_Load加载函数和通用的AEEMod_Load具体实现几乎一样,最主要的区别在于其调用AEEStaticMod_New时指定了pfnMC参数,即static module需要指定自身的createinstance函数。 4. Module 创建 这是通过 在AEEStaticMod_New中代码 modFuncs->CreateInstance = AEEMod_CreateInstance;指定的 AEEMod_CreateInstance函数来创建的。我们来看一下AEEMod_CreateInstance的庐山真面目: static int AEEMod_CreateInstance(IModule *pIModule,IShell *pIShell, AEECLSID ClsId,void **ppObj) { AEEMod *pme = (AEEMod *)pIModule; int nErr = 0;
// For a dynamic module, they must supply the AEEClsCreateInstance() // function. Hence, invoke it. For a static app, they will have // registered the create Instance function. Invoke it. if (pme->pfnModCrInst) { nErr = pme->pfnModCrInst(ClsId, pIShell, pIModule, ppObj); #if !defined(AEE_STATIC) } else {
JAVA手机网[www.cnjm.net] nErr = AEEClsCreateInstance(ClsId, pIShell, pIModule, ppObj); #endif }
return nErr; }
可见对于dynamic module,由于pme->pfnModCrInst为NULL,所以调用通用的创建函数AEEClsCreateInstance(ClsId, pIShell, pIModule, ppObj)来进行创建。而对于static module,因为指定了自身的Createinstance函数,所以pme->pfnModCrInst不为NULL,从而执行特定于该module自身的createinstance函数 5. Applet创建
JAVA手机网[www.cnjm.net] 之后,不管是 AEEClsCreateInstance还是pme->pfnModCrInst其实都是类似的,通过AEEApplet_New(除extension class外通常都是调用该函数)来最终创建applet,AEEApplet_New无非是具体分配applet内存,初始化applet的vtbl(这里最重要的是实例化applet_handleevent)并返回Iapplet指针,供运行时使用
JAVA手机网[www.cnjm.net] 6. 程序运行 通常就是在applet_handleevent中进行各种事件处理。处理前一般将传入的Iapplet指针先转换为AEEApplet或者用户自身的结构,以便可以访问其中的数据变量。
以上就是我对BREW模块加载机制的理解。大家相互交流
来自:http://www.cnjm.net/tech/article846.html
|
|
|
|
|
|
相关文章
暂无相关文章
|
|
| 最新评论
|
|
|
|