OHOS标准系统的SAMGR代码解读(v3.1)--2--samgr 原创 精华
::: hljs-center
OHOS标准系统的SAMGR代码解读(v3.1)–2–samgr
梁开祝 20220907
:::
前文:
OHOS标准系统的SAMGR代码解读(v3.1)–0–前言
OHOS标准系统的SAMGR代码解读(v3.1)–1–safwk
OHOS标准系统的samgr组件位于3.1分支代码的//foundation/distributedschedule/samgr/目录下,在最新的master分支代码则是//foundation/systemabilitymgr/samgr/目录下。
1. samgr 组件的全景图
先看samgr组件的全景图(附件有大图)
从上图中的代码目录结构和编译脚本部分,可以看到5个编译目标以及它们各自编译的代码:
- samgr_common:公共部分,提供SA Profile的解析工具、动态链接库的加载和卸载等功能,主要用在上一篇分析的safwk的工作流程中,本文不再赘述。
- lsamgr:local samgr的客户端代理,主要用于按需启动指定的SA;该功能也同时编译进samgr_proxy模块中(一并在samgr_proxy中分析)。
- samgr_proxy:samgr的客户端代理。SA通过该代理提供的接口与samgr服务进行交互,同时也为samgr服务向SA客户端反馈SA的加载结果、订阅的SA的状态变化等功能提供Stub接口。
- 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 类对象manager的创建和Init()之后,就生成了全景图右下角部分所示的结构;然后通过IPCSkeleton::SetContextObject()将 manager 作为远程对象注册到IPC模块,为以后的IPC/RPC提供IRemoteObject;最后samgr服务的主线程进入loop,开始为整个系统中的SA提供服务。
接下来的内容,请结合samgr组件的全景图和下面的IPC交互示意图进行理解。
3. samgr 服务端的类结构
samgr 服务端主要的类结构和继承关系,见全景图的右下角以ohos_executable(“samgr”)为起点的部分。
3.1 SA死亡回调相关的成员和RPC回调相关的成员
在 SystemAbilityManager::Init() 中创建并初始化的与SA死亡回调相关的成员、RPC回调相关的成员,这里先放下不说,请小伙伴先自行阅读代码理解。
3.2 SystemAbilityLoadCallbackProxy 和 SystemAbilityStatusChangeProxy
在 SystemAbilityManager 类提供的服务中,samgr会根据需要调用相关的接口向samgr_proxy发送IPC消息,以此向Proxy反馈SA的加载状态、上线离线状态等信息,见4.2节的简介。
3.3 SystemAbilityManagerStub 和 SystemAbilityManager
samgr服务端的主要工作在这两个类中。
在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”)为起点的部分。
4.1 LocalAbilityManagerProxy
LocalAbilityManagerProxy类提供了向指定进程发送IPC消息拉起按需启动的SA的Proxy接口,由指定进程中的LocalAbilityManagerStub接收消息,并执行动态拉起SA的具体动作(如上一篇分析4.3节分析所示)。
例如,不管是同设备内的进程还是跨设备的进程,在调用:
sptr<IRemoteObject> SystemAbilityManager::CheckSystemAbility(int32_t systemAbilityId, bool& isExist)
向samgr查询SA时,samgr会先在已启动的 abilityMap_ 中查找目标SA,能找到,则表明SA已经启动了;找不到,则继续在正在启动的 startingAbilityMap_ 中查找目标SA,能找到,则表明SA正在启动中;还找不到,则会尝试调用StartOnDemandAbility(SAID)来启动目标SA(即按需启动SA)。StartOnDemandAbility(SAID)会在登记到onDemandAbilityMap_中的按需启动的SA列表中查找匹配SAID的记录,并通过SystemAbilityManager::StartOnDemandAbilityInner()向SAID所在进程发送IPC消息,要求该进程拉起对应的SA,如下代码片段所示:
void SystemAbilityManager::StartOnDemandAbilityInner(const std::u16string& procName, int32_t systemAbilityId,
AbilityItem& abilityItem)
{
......
//从 systemProcessMap_ 中获取 LocalAbilityManagerProxy procObject
sptr<ILocalAbilityManager> procObject =
iface_cast<ILocalAbilityManager>(GetSystemProcess(procName));
......
//调用 LocalAbilityManagerProxy::StartAbility
//向 LocalAbilityManagerStub 发送IPC消息拉起参数指定的SA
procObject->StartAbility(systemAbilityId);
......
}
4.2 SystemAbilityLoadCallbackStub 和 SystemAbilityStatusChangeStub
当进程A向samgr注册SA_a时,samgr会调用:
void SystemAbilityManager::SendSystemAbilityAddedMsg(int32_t systemAbilityId, const sptr<IRemoteObject>& remoteObject)
{
......
auto notifyAddedTask = [systemAbilityId, remoteObject, this]() {
FindSystemAbilityNotify(systemAbilityId, ADD_SYSTEM_ABILITY_TRANSACTION);
NotifySystemAbilityLoaded(systemAbilityId, remoteObject);
};
bool ret = workHandler_->PostTask(notifyAddedTask);
......
}
其中的FindSystemAbilityNotify()会在 listenerMap_ 中查找监听SA_a状态变化的监听者,并调用listener的回调函数,通过SystemAbilityStatusChangeProxy向SystemAbilityStatusChangeStub发送SA_a上线或离线的消息。listener所在的进程B、进程C…的SystemAbilityStatusChangeStub就可以收到该消息并做针对性地处理。
其中的NotifySystemAbilityLoaded()也会通过SystemAbilityLoadCallbackProxy向SystemAbilityLoadCallbackStub 发送SA_a加载成功的IPC消息到查询SA_a的进程B中,这样进程B中的SystemAbilityLoadCallbackStub 就可以收到该消息并做针对性地处理。
4.3 SystemAbilityManagerProxy和 SystemAbilityManagerClient
进程A必须要通过代理才能与samgr进行交互(如注册SA、查询SA等)。
如进程A在启动SA_a时,必须要先通过CheckSystemAbilityManagerReady() 确认samgr可以访问:
bool LocalAbilityManager::CheckSystemAbilityManagerReady()
{
......
//获取samgr的代理:SystemAbilityManagerProxy
sptr<ISystemAbilityManager> samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
while (samgrProxy == nullptr) {
HILOGI(TAG, "waiting for SAMGR...get 'samgrProxy'...");
if (timeout > 0) {
usleep(duration);
samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
} else {
HILOGE(TAG, "waiting for SAMGR...timeout[10s]...NGNGNG");
return false;
}
timeout--;
}
......
return true;
}
即能够成功获取samgr的代理SystemAbilityManagerProxy,这样SA_a才能注册到samgr中,否则表示samgr还没有能够正常工作,所有的SA_x都无法注册,所以可以说samgr进程是最早启动的系统服务进程了。
类似的,在系统中各个进程需要与samgr进行交互的时候,都是按下面这个流程进行的:
//先获取samgr的代理:SystemAbilityManagerProxy
sptr<ISystemAbilityManager> samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
//再通过该代理向samgr发送IPC消息,使用samgr提供的服务
samgrProxy->XxxYyy()
5.Proxy与Stub的IPC交互
一图胜千言,两图胜两千言。
请结合前面两张图自行阅读代码进行理解。
文中图看不清的小伙伴可以下载附件,附件中有高清大图。
有图表还是比读文字舒服多了
字不如表,表不如图!
大佬,书出版了吗?有电子版的吗,最近在学习这部分代码,有偿!
纸质书已经在出版社排版印刷了,预计下个月可上市。是否出电子版由出版社确定,目前暂不能提供。
“最近在学习这部分代码”如果是指分布式任务调度子系统,在我的专栏里就有分析这部分代码的一组博文,对你应该有所帮助。
想问一个问题,“samgr服务在OHOS系统中几乎是最早启动的系统服务”,请问这里说到的系统服务就是系统能力SA的意思吗?如果不是,请问系统服务和系统能力的区别是什么?
samgr比safwk先启动吗?
这里的系统服务就是指系统能力(System Ability),在OHOS中,所有的系统能力都是以服务的形式来对外提供服务(能力、功能、接口)的,所以系统能力也称为系统服务。在master分支代码上,原先的distributedschedule子系统已经改名为systemabilitymgr子系统,而samgr和safwk都是该子系统的组件。
safwk自己并不能作为一个单独或独立的进程来运行,它是一个或多个服务(如标准系统的dsoftbus服务)运行起来的框架(或躯壳),它为服务进程创建或提供运行起来的基础环境。服务自己的动态链接库(如dsoftbus的 libsoftbus_server.z.so)则是服务通过safwk加载并运行起来后要去运行的主体(或灵魂)。
正常情况下,一定是samgr先启动和运行起来,其它的服务(不管是否通过safwk启动)需要向samgr注册SA。如果其它服务通过safwk先于samgr运行起来,则该服务会在获取samgrProxy这一步失败,然后会马上终止启动,返回异常而退出。该服务进程的父进程(Init进程)收到子进程异常退出信号之后,会尝试重新启动该服务。一般来说samgr启动起来之后,别的服务就可以获取samgrProxy并正常注册SA了。
我说“samgr服务在OHOS系统中几乎是最早启动的系统服务”,是因为确实还有比samgr更早启动的系统服务(如 ueventd),因为 ueventd 并不是普通意义上的系统服务,不需要向samgr注册SA才能工作(就是说这些服务不需要通过samgr的管理才能向系统提供服务)。