当前位置: 首页 > 科技观察

OHOS标准体系(v3.1)SAMGR代码解读--2--Samgr

时间:2023-03-16 21:38:42 科技观察

更多开源信息请访问:开源基础软件社区https:///ost.51cto.comOHOS标准系统的samgr组件位于3.1分支代码的//foundation/distributedschedule/samgr/目录下,最新的master分支代码在//foundation/systemabilitymgr/samgr/目录。一、samgr组件全景图首先看samgr组件全景图(附件中有大图)。从上图的代码目录结构和编译脚本部分,可以看到5个编译目标和各自的编译代码:samgr_common:公共部分,提供SAProfile分析工具,动态链接库加载卸载等功能,主要是它在上一篇分析的safwk的工作流程中用到了,本文不再赘述。lsamgr:localsamgrclientproxy,主要用于按需启动指定的SA;这个函数也被编译到samgr_proxy模块中(一起在samgr_proxy中解析)。samgr_proxy:samgr的客户端代理。SA通过proxy提供的接口与samgr服务进行交互,同时也为samgr服务提供Stub接口,将SA的加载结果和订阅的SA的状态变化反馈给SA客户端。samgr_init:samgr服务自启动的配置文件,与samgr可执行程序配合使用。samgr:samgr服务的可执行程序实体,结合samgr_init的配置,在系统启动初期自动运行,拉起samgr服务。同时,它还通过Proxy向SA客户端反馈SA的加载结果、订阅的SA的状态变化事件等信息。虽然IPC相关结构画成全景图,但本文并没有深入分析IPC/RPC。因此,以下部分重点介绍samgr服务的实现和samgr_proxy客户端的实现。2、samgr服务的启动过程samgr服务几乎是OHOS系统中最早启动的系统服务,在OHOS中占有重要的通信中心地位(可以参考我分析的samgr_lite系列文章)理解)。samgr服务的启动过程如全景图的左下角所示,看起来比较简单。完成SystemAbilityManager类对象管理器的创建和Init()后,生成全景图右下角所示结构;然后通过IPCSkeleton::SetContextObject()将管理器作为远程对象注册到IPC模块,为以后的IPC/RPC提供IRemoteObject;最后samgr服务的主线程进入循环,开始为整个系统的SA提供服务。下面的内容请结合samgr组件全景图和下面的IPC交互图来理解。3、samgrserver的类结构samgrserver的主要类结构和继承关系,见全景图右下角ohos_executable(“samgr”)开始的部分。(1)SA死亡回调相关成员和RPC回调相关成员在SystemAbilityManager::Init()中创建并初始化SA死亡回调和RPC回调相关成员先阅读代码理解。(2)SystemAbilityLoadCallbackProxy和SystemAbilityStatusChangeProxy属于SystemAbilityManager类提供的服务。Samgr会根据需要调用相关接口向samgr_proxy发送IPC消息,从而将SA加载状态、在线离线状态等信息反馈给Proxy。请参阅第4.2节中的介绍。(3)SystemAbilityManagerStub和SystemAbilityManagersamgr服务器的主要工作就在这两个类中。samgr进程启动过程中创建SystemAbilityManager对象时,会在SystemAbilityManagerStub的构造函数中初始化一个memberFuncMap_,将Stub要处理的消息代码与处理函数关联起来。SystemAbilityManagerStub收到SystemAbilityManagerProxy的IPC消息后,直接匹配memberFuncMap_中的消息编码,转而调用子类SystemAbilityManager的函数做具体的服务工作,必要时将处理结果返回给SystemAbilityManagerProxy。3.1和3.2中的工作也是由SystemAbilityManager类发起或者直接处理。4.samgr_proxy的类结构samgr_proxy相关的类结构和继承关系参见全景图中ohos_shared_library(“samgr_proxy”)开始的部分。(1)LocalAbilityManagerProxyLocalAbilityManagerProxy类提供Proxy接口,向指定进程发送IPC消息,拉起按需启动的SA。指定进程中的LocalAbilityManagerStub收到消息,执行动态拉起SA的具体动作(如前文4.3节分析所示)。例如,无论是同一设备内的进程还是跨设备的进程,当调用:sptrSystemAbilityManager::CheckSystemAbility(int32_tsystemAbilityId,bool&isExist)从samgr中查询SA时,samgr会先在中搜索目标thestartedabilityMap_如果能找到SA,说明SA已经启动;如果找不到,则继续在startingAbilityMap_中寻找目标SA,如果能找到,说明SA正在启动;如果找不到,它会尝试调用StartOnDemandAbility(SAID)来启动目标SA(即按需启动SA)。StartOnDemandAbility(SAID)会在onDemandAbilityMap_注册的按需启动SA列表中查找匹配SAID的记录,并通过SystemAbilityManager::StartOnDemandAbilityInner()向SAID所在进程发送IPC消息,要求进程拉起对应的SA。如下代码片段所示:voidSystemAbilityManager::StartOnDemandAbilityInner(conststd::u16string&procName,int32_tsystemAbilityId,AbilityItem&abilityItem){......//从systemProcessMap获取LocalAbilityManagerProxyprocObject_sptrprocObject=ifaceAbility_castStartAbility(systemAbilityId)指定的SA;......}(2)SystemAbilityLoadCallbackStub和SystemAbilityStatusChangeStub当进程A向samgr注册SA_a时,samgr会调用:远程对象ject,this](){FindSystemAbilityNotify(systemAbilityId,ADD_SYSTEM_ABILITY_TRANSACTION);NotifySystemAbilityLoaded(systemAbilityId,remoteObject);};boolret=workHandler_->PostTask(notifyAddedTask);......}其中FindSystemAbilityNotify()会在listenerMap_中找到监听SA_a状态变化的监听器,调用监听器的回调函数,通过SystemAbilityStatusChangeProxy向SystemAbilityStatusChangeStub发送SA_a在线或离线消息。监听器所在进程B和进程C的SystemAbilityStatusChangeStub可以接收到消息并进行针对性处理。其中NotifySystemAbilityLoaded()还会通过SystemAbilityLoadCallbackProxy向SystemAbilityLoadCallbackStub发送SA_a加载成功的IPC消息给查询SA_a的进程B,以便进程B中的SystemAbilityLoadCallbackStub接收到该消息并进行针对性处理。(3)SystemAbilityManagerProxy和SystemAbilityManagerClient进程A必须通过代理才能与samgr进行交互(如注册SA、查询SA等)。例如进程A启动SA_a时,首先要确认samgr可以通过CheckSystemAbilityManagerReady()访问:boolLocalAbilityManager::CheckSystemAbilityManagerReady(){......//获取samgr的代理:SystemAbilityManagerProxysptrsamgrProxy=SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();while(samgrProxy==nullptr){HILOGI(TAG,"等待SAMGR...获取'samgrProxy'...");如果(超时>0){usleep(持续时间);samgrProxy=SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();}else{HILOGE(TAG,"等待SAMGR...超时[10s]...NGNGNG");返回假;}暂停-;}......returntrue;}表示可以成功获取到samgr的代理SystemAbilityManagerProxy,这样就可以在samgr中注册SA_a,否则说明samgr还不能正常工作,所有SA_x都不能被注册,所以可以说samgr进程是第一个启动的系统服务进程就结束了。同理,当系统中的各个进程需要与samgr进行交互时,都是按照以下流程进行的://首先获取samgr的代理:SystemAbilityManagerProxysptrsamgrProxy=SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();//然后通过proxy向samgr发送IPC消息,使用samgr提供的服务samgrProxy->XxxYyy()。5、Proxy和Stub的IPC交互值一千字,两张图值两千字。请结合前面两张图自行阅读代码理解。文章相关附件可点击下方原文链接下载:https://ost.51cto.com/resource/2287。了解更多开源知识,请访问:开源基础软件社区https://ost.51cto.com。