一、前言
在针对鸿蒙模块二的源代码分析中,发现它业务逻辑的实现围绕着三大概念展开,分别是服务(Service)、功能(Feature)和功能接口API(Iunknown)。所以理解并掌握这三个概念对于我们深入学习鸿蒙底层代码的业务逻辑有极大的帮助。下面我将结合前期分析鸿蒙代码的经验,通过图文并茂的方式为读者讲解它们的基类和实例对象以及相应的作用。
二、基类分析
服务(Service)是鸿蒙操作系统中业务逻辑的核心,是一组功能或操作的集合。下面的结构体定义了服务基类的相关函数指针,所有服务都要继承这个基类。
struct Service {
const char *(*GetName)(Service *service); //获取服务名称
BOOL (*Initialize)(Service *service, Identity identity); //初始化服务
BOOL (*MessageHandle)(Service *service, Request *request); //处理服务的消息
TaskConfig (*GetTaskConfig)(Service *service); //获取服务的任务配置
};
一个服务可以拥有多个功能(Feature),功能是业务的执行单元。由各式各样的功能组合成一个完整的服务。下面的结构体定义了功能基类的相关函数指针,所有功能都要继承这个基类。
struct Feature {
const char *(*GetName)(Feature *feature); //获取功能名称
void (*OnInitialize)(Feature *feature, Service *parent, Identity identity); //初始化功能
void (*OnStop)(Feature *feature, Identity identity); //停止功能
BOOL (*OnMessage)(Feature *feature, Request *request); //处理功能消息
};
-
IUnknown
通过上述服务和功能的概念抽象出鸿蒙完整的业务逻辑模型。一个服务包含零个到多个功能。在鸿蒙代码中,针对服务和功能的调用还提供了统一的对外接口(Iunknown)。下面的结构体定义了接口基类的相关函数指针,所有对外接口都要继承这个基类。
struct IUnknown {
int (*QueryInterface)(IUnknown *iUnknown, int version, void **target);//查询指定版本的IUnknown接口的子类对象
int (*AddRef)(IUnknown *iUnknown); //添加引用计数
int (*Release)(IUnknown *iUnknown); //释放引用计数
};
三、实例对象
在后续服务和功能的注册、启动等过程中都是使用ServiceImpl和FeatureImpl。它们的定义如下:
功能绑定接口后的实例对象
一个功能对应一个接口,作为一个功能的实例对象
struct FeatureImpl {
Feature *feature; //功能对象
IUnknown *iUnknown; //对外的接口
};
服务绑定接口后的实例对象
一个服务至少向外提供一个API接口(当服务下面没有注册功能时,向外暴露defaultApi)。也可以提供多个API接口(当服务下面注册多个功能时,每一个功能都有一个API接口)。一个服务对应一个任务池。
struct ServiceImpl {
Service *service; //服务对象
IUnknown *defaultApi; //默认的对外接口
TaskPool *taskPool; //绑定的任务池
Vector features; //已注册的FeatureImpl对象
int16 serviceId; //服务ID,位于g_samgrImpl的vector中的下标
uint8 inited; //服务所处的状态
Operations ops; //操作信息,记录一些运维信息
};
服务和功能实例对象的图示
ServiceImpl:Vector的data指向一个FeatureImpl类型的指针数组,每个指针指向一个FeatureImpl对象。TaskPool指向一个TaskPool对象。图中只画出了部分重要字段。 注:任务池的绑定分为三种:
1.SHARED_TASK,根据service的优先级共享任务,此时绑定的是SamgrLiteImpl中维护的共享任务池。
2.SPECIFIED_TASK,为service绑定指定的任务池,遍历所有的ServiceImpl对象,查找相同任务配置的任务池,若找到则绑定,若未找到则创建新的任务池。
3.SINGLE_TASK,根据任务配置,创建新的任务池并绑定。
四、注册过程
这里先简单的介绍一下服务和功能的注册,在后续文章中再详细介绍函数的调用过程。提到服务的注册我们还需要了解一个重要的数据结构SamgrLiteImpl,在代码中有一个由它定义的全局变量g_samgrImpl,这个全局变量维护了一系列的服务,也称为系统功能管理器(Samgr)。结构体定义如下:
struct SamgrLiteImpl {
SamgrLite vtbl; //SamgrLite类管理一些函数,用于注册和发现服务和功能
MutexId mutex; //互斥锁
BootStatus status; //系统功能管理器(samgr)的状态
Vector services; //已注册的ServiceImpl对象
TaskPool *sharedPool[MAX_POOL_NUM]; //服务共享的任务池
};
注册的过程分为接口的注册、功能的注册和服务的注册。流程如下:
1.Feature绑定IUnknown封装为FeatureImpl对象。(接口的注册)
2.将FeatureImpl对象添加到ServiceImpl的vector集合中。(功能的注册)
3.将ServiceImpl对象添加到SamgrLiteImpl的vector集合中。(服务的注册)
Samgr实例图示
SamgrLiteImpl:Vector的data指向一个ServiceImpl类型的指针数组,每个指针指向一个ServiceImpl对象。TaskPool指向一个TaskPool类型的指针数组,每个指针指向一个TaskPool,这一点与ServiceImpl中是不同的。图中只画出了部分重要字段。 注:当ServiceImpl中task的taskflags即任务类型为SHARED_TASK时,根据任务的优先级共享SamgrLiteImpl中TaskPool维护的指定任务池。