更多信息请访问:https://harmonyos.51cto.com,与华为官方共建的鸿蒙技术社区。1.初步了解,先阅读README文档,位于LTS/foundation/distributedschedule/samgr_lite/README_zh.md。我们先对其中的一些内容做一个初步的了解。系统服务框架[systemability(SA)framework]是为屏蔽不同硬件架构、不同平台资源、不同运行形态等软硬件差异而提供的统一的系统服务开发框架。根据处理器架构的不同,如RISC-V架构(一种基于精简指令集RISC的开源架构)、ARM架构(如ARM的Cortex-M/Cortex-A等)、x86架构(主要用于PC市场,目前鸿蒙暂时不支持,但可能会宣布哪天支持)等,目前分为两类硬件平台,以下简称M核(平台)和一个核心(平台)。M核:处理器架构为Cortex-M或具有同等处理能力的硬件平台。系统内存一般小于512KB。不提供文件系统或仅提供用途有限的轻量级文件系统,遵循CMSIS接口规范。CoreA:处理器架构为Cortex-A或同等处理能力的硬件平台,内存资源大于512KB,文件系统完备,可存储大量数据,遵循POSIX接口规范。系统服务框架基于面向服务架构(SOA,Service-OrientedArchitecture),提供服务(service)开发、服务子功能(feature)开发、对外接口(IUnknown)开发、多服务协同-进程和进程间开发能力,如服务调用。其中:M-core:包括服务开发、服务子功能开发、对外接口开发、多服务协程开发框架。核心A:在M核心能力的基础上,包括进程间服务调用、进程间服务调用权限控制、进程间服务接口开发等能力。依赖方面:M核心:系统依赖bootstrap服务,在系统启动函数中调用HOS_SystemInit()函数。核心A:系统依赖samgr库,在main函数中调用了SAMGR_Bootstrap()函数。我的简单理解:samgr是一个系统服务开发框架。开发者可以根据这里指定的规则开发自定义的服务和功能(service+feature)、接口等。示例程序在Hi3861/applications/sample/wifi-iot/app/samgr/,打开BUILD.gn的编译规则参与编译。示例程序可能存在编译错误,可以在gitee上获取最新代码进行对比修改,或者参考《WiFi IoT 编译samgr模块》进行修改。编译后的程序可能会出现内核恐慌。我估计很大的原因是一次性注册启动的服务/特性/任务太多,导致系统资源耗尽,所以最好只编译需要验证的部分。不要一次编译所有示例程序。我后面贴的log是只编译service_example.c和feature_example.c抓取的。Samgr提供对所有服务、特性和接口的统一管理,包括跨设备的服务/特性管理和调度,这是鸿蒙系统的核心特性之一。2.代码目录结构首先看一下LTS/foundation/distributedschedule/samgr_lite/的代码结构:看起来比较复杂。看对应的Hi3861/foundation/distributedschedule/代码结构:两者对比其实大致相同。进入Hi3861/foundation/distributedschedule/service/samgr_lite/目录下可以看到BUILD.gn文件的构建规则,将只在A核上编译的部分打灰,如上表所示,其余基本使用由M核心。本文只是从Hi3861项目的角度来看samgr子系统,所以代码基本只需要阅读:Hi3861/foundation/distributedschedule/service/samgr_lite/communication/broadcast/Hi3861/foundation/distributedschedule/service/samgr_lite/samgr/source/因为samgr“依赖于bootstrap服务”,所以它也依赖于Hi3861/base/startup/services/bootstrap_lite/的代码。至于:Hi3861/foundation/distributedschedule/service/samgr_lite/samgr/adapter/这是屏蔽调用者平台差异的统一接口的声明和实现,暂不深入研究。hi3861/foundation/distributedschedule/service/samgr_lite/samgr/registry/这里定义了三个弱引用API:SAMGR_RegisterServiceApi()SAMGR_FindServiceApi()SAMGR_RegisterFactory()它们在/samgr_server/source/samgr_server.c中实现,估计和span有关设备的服务调用,但是M核并没有编译samgr_server,所以M核的上述三个API并没有做太多的工作,这里不再深究。这样一来,清理相关代码和模块关系就会容易很多,上手也相对容易。让我们开始“阅读他妈的源代码:)”。3.一般流程当Hi3861平台启动到HOS_SystemInit()时,voidHOS_SystemInit(void){......printf("[system_init][7-4]:SYS_INIT(service)=======================\n");SYS_INIT(服务);printf("[system_init][7-5]:SYS_INIT(feature)======================\n");SYS_INIT(feature);......printf("[system_init][7-7]:SAMGR_Bootstrap()=======================\n");SAMGR_Bootstrap();}会分别经过以上三个步骤:向samgr注册系统服务(service),注册函数(feature)由系统服务提供,并通过samgr启动,开始管理系统服务和功能。从抓回来的日志看:[system_init][7-4]:SYS_INIT(service)=====================[bootstrap_service]SYS_SERVICE_INIT(Init):Bootstrap[samgr_lite]SAMGR_GetInstance(mutex=NULL):NOSAMGRinstance,Init()创建一个[samgr_lite]Init.g_samgrImpl[samgr_lite]Init.mutex[956036].sharedPool[0-8]resetto0.status=0[BOOT_SYS][samgr_lite]SAMGR_GetInstance(mutex=956036)[samgr_lite]RegisterService(Name:Bootstrap)->Sid[0][broadcast_service]SYS_SERVICE_INIT(Init):Broadcast[samgr_lite]RegisterService(Name:Broadcast)->Sid[1][hiview_service]SYS_SERVICE_INIT(Init)):hiview[samgr_lite]RegisterService(Name:hiview)->Sid[2][samgr_lite]RegisterFeatureApi(serviceName[hiview],feature[(null)])[hiview_service]Init.InitHiviewComponent.[system_init][7-5]:SYS_INIT(feature)=====================[pub_sub_feature]Init.SYS_FEATURE_INIT(Init)g_broadcastFeature:Providerandsubscriber[samgr_lite]RegisterFeature(serviceName:Broadcast,featureName:Providerandsubscriber)->Fid[0][pub_sub_implement]BCE_CreateInstance:setg_pubSubImplement.feature=&g_broadcastFeature[samgr_lite]RegisterFeatureApi(serviceName[Broadcast],feature[Providerandsubscriber])将注册三个系统服务和一个系统功能。第一个注册的系统服务是Bootstrap。此时samgr还没有实例,所以需要先初始化samgr的全局实例g_samgrImpl,然后通过RegisterService((Service*)&bootstrap)向g_samgrImpl注册bootstrap服务。此时g_samgrImpl会通过SAMGR_CreateServiceImpl()创建一个用于bootstrap的ServiceImpl对象,将该对象添加到g_samgrImpl.servicesvector中,返回其在vector中的位置[0]作为bootstrap的ServiceID[0](文中或Log简写为Sid,FeatureID简写为Fid,QueueID简写为Qid)。接下来注册的第二个servicebroadcast和第三个servicehiview可以直接通过RegisterService((Service*)Xxx)记录到g_samgrImpl.servicesvector中,Sids分别为[1]/[2]。接下来,注册广播服务的特性:PUB_SUB_FEATURE。一个特征的注册和运行依赖于相应的服务。一个服务可以有0个、1个或更多的特性。通过RegisterFeature(service,feature)的调用,samgr也会先生成一个FeatureImpl对象,然后将该对象添加到g_samgrImpl.services向量中对应服务的ServiceImpl对象的向量特征中,完成特征的注册.这句话看起来很绕。简单的说,g_samgrImpl的servicesvector管理着所有注册服务的ServiceImpl,每个ServiceImpl通过自己的featuresvector来管理自己的所有features。【更具体的实现过程后面会有详细的代码分析。】在接下来的系统运行中,serviceName/serviceID(Sid)和featureName/featureID(Fid)是非常重要的信息,samgr可以通过它们找到对应的ServiceImpl/FeatureImpl对象,并提供对应的服务/功能。[system_init][7-7]:SAMGR_Bootstrap()=======================[samgr_lite]SAMGR_Bootstrap.Begin:size=3InitializeAllServices:size=3Addservice:BootstraptoTaskPool:0x0...TaskPool:0xfa448...Qid:956360...??Addservice:BroadcasttoTaskPool:0x0...TaskPool:0xfaab8...Qid:956404...Addservice:hiviewtoTaskPool:0x0...TaskPool:0xfac78...Qid:956448...[task_manager]SAMGR_StartTaskPool:CreateTask[Bootstrap(Tid:0xe8780),size(8192),Prio(25)]-OK![task_manager]SAMGR_StartTaskPool:CreateTask[广播(Tid:0xe871c)),size(4096),Prio(32)]-OK![task_manager]SAMGR_StartTaskPool:CreateTask[hiview(Tid:0xe87e4),size(2048),Prio(24)]-OK![samgr_lite]SAMGR_Bootstrap.End。这里是samgrStart为g_samgrImpl.services向量中注册的每个服务创建Queue和TaskPool运行环境。在SAMGR_StartTaskPool()步骤中,依次创建和启动服务任务/线程。线程入口是TaskEntry()函数,位于Hi3861/foundation/distributedschedule/services/samgr_lite/samgr/source/task_manager.c文件中。每个服务的TaskEntry线程监听各自的消息队列Queue,从中检测消息,获取Exchange封装的数据,根据里面的相关标签调用相关的msghandler进行相应的处理。上述过程只启动了标有SYS_SERVICE_INIT()和SYS_FEATURE_INIT()的服务和特性,以及标有SYSEX_SERVICE_INIT/APP_SERVICE_INIT/SYSEX_FEATURE_INIT/APP_FEATURE_INIT的服务和特性(作为上述示例程序samgr中定义的服务和特性的一部分),当系统启动到BOOT_APP步骤时,通过发送消息BOOT_SYS_COMPLETED到Bootstrap消息队列,让Bootstrap调用MessageHandle()处理消息:通过调用INIT_APP_CALL(service)和INIT_APP_CALL(feature)完成启动APP服务和Feature来提供用户定义的服务和功能。以上就是服务/特性注册和启动的大致流程。主要工作由samgr实现,是samgr_lite组件的基础代码部分提供的功能。log和简单步骤说明见附件log。接下来,我将分解一些重要的结构,详细分析一些过程。更多信息请访问:Harmonyos.51cto.com,与华为官方合作打造的鸿蒙技术社区
