系统服务框架子系统

简介

这个仓库用于存放系统服务框架的代码。由于平台资源有限,且硬件平台多样,因此需要屏蔽不同硬件架构和资源的不同、以及运行形态的不同,提供统一化的系统服务开发框架。根据RISC-V、Cortex-M、Cortex-A不同硬件平台,分为两种平硬件平台,以下简称M核、A核。

M核:处理架构为Cortex-M或同等处理能力的硬件平台,系统内存一般低于512KB,无文件系统或者仅提供一个可有限使用的轻量级文件系统,遵循CMSIS接口规范。

A核:处理架构为Cortex-A或同等处理能力的硬件平台,内存资源大于512KB,文件系统完善,可存储大量数据,遵循POSIX接口规范。

系统服务框架基于面向服务的架构,提供了服务开发、服务的子功能开发、对外接口的开发、以及多服务共进程、进程间服务调用等开发能力。其中:

  • M核:包含服务开发、服务的子功能开发、对外接口的开发以及多服务共进程的开发框架。
  • A核:在M核能力基础之上,包含了进程间服务调用、进程间服务调用权限控制、进程间服务接口的开发等能力。

面向服务的架构:

系统服务框架子系统 - 图1

Provider:服务的提供者,为系统提供能力(对外接口)。

Consumer:服务的消费者,调用服务提供的功能(对外接口)。

Samgr:做为中介者,管理Provider提供的能力,同时帮助Consumer发现Provider的能力。

系统服务开发框架主体对象:

系统服务框架子系统 - 图2

  • SamgrLite:主要提供服务的注册与发现能力。
  • Service:开发服务时,需要实现的服务的生命周期接口。
  • Feature:开发功能时,需要实现的功能的生命周期接口。
  • IUnknown:基于IUnknown开发服务或功能的对外接口。
  • IClientProxy:IPC调用时,消费者的消息发送代理。
  • IServerProxy:IPC调用时,开发者需要实现的,生产者的消息处理代理。

目录

表 1 系统服务框架源代码目录结构

名称

描述

interfaces/kits/samgr_lite/samgr

M核和A核系统服务框架对外接口定义。

interfaces/kits/samgr_lite/registry

A核进程间服务调用的对外接口定义。

interfaces/kits/samgr_lite/communication/broadcast

M核和A核进程内事件广播服务的对外接口定义。

services/samgr_lite/samgr/adapter

POSIX和CMSIS接口适配层来屏蔽A核M核接口差异。

services/samgr_lite/samgr/registry

M核服务注册发现的桩函数。

services/samgr_lite/samgr/source

M核和A核系统服务开发框架基础代码。

services/samgr_lite/samgr_client

A核进程间服务调用的注册与发现。

services/samgr_lite/samgr_server

A核进程间服务调用的IPC地址管理和访问控制。

services/samgr_lite/samgr_endpoint

A核IPC通信消息收发包管理。

services/samgr_lite/communication/broadcast

M核和A核进程内事件广播服务。

约束

系统服务开发框架统一使用C开发。

同进程内服务间调用统一使用IUnknown接口对外象,消息接口统一由IUnknown接口传递给本服务。

服务名和功能名必需使用常量字符串且长度小于16个字节。

M核:系统依赖上bootstrap服务,在系统启动函数中调用HOS_SystemInit()函数。

A核:系统依赖samgr库,在main函数中调用SAMGR_Bootstrap()函数。

开发服务

  • 继承并重新定义服务:

    1. typedefstructExampleService{
    2. INHERIT_SERVICE;
    3. INHERIT_IUNKNOWNENTRY(DefaultFeatureApi);
    4. Identity identity;
    5. }ExampleService;
  • 实现服务的生命周期函数:

    1. staticconstchar*GetName(Service*service)
    2. {
    3. return EXAMPLE_SERVICE;
    4. }
    5. static BOOL Initialize(Service*service,Identity identity)
    6. {
    7. ExampleService*example =(ExampleService*)service;
    8. // 保存服务的唯一身份标识,用来自己的IUnknown接口对服务发消息时使用。
    9. example->identity = identity;
    10. return TRUE;
    11. }
    12. static BOOL MessageHandle(Service*service,Request*msg)
    13. {
    14. ExampleService*example =(ExampleService*)service;
    15. switch(msg->msgId){
    16. case MSG_SYNC:
    17. // 业务处理
    18. break;
    19. default:break;
    20. }
    21. return FALSE;
    22. }
    23. staticTaskConfigGetTaskConfig(Service*service)
    24. {
    25. TaskConfig config ={LEVEL_HIGH, PRI_BELOW_NORMAL,
    26. 0x800,20, SHARED_TASK};
    27. return config;
    28. }
  • 创建服务对象:

    1. staticExampleService g_example ={
    2. .GetName=GetName,
    3. .Initialize=Initialize,
    4. .MessageHandle=MessageHandle,
    5. .GetTaskConfig=GetTaskConfig,
    6. SERVER_IPROXY_IMPL_BEGIN,
    7. .Invoke= NULL,
    8. .SyncCall=SyncCall,
    9. IPROXY_END,
    10. };
  • 向SAMGR注册服务及接口:

    1. staticvoidInit(void)
    2. {
    3. SAMGR_GetInstance()->RegisterService((Service*)&g_example);
    4. SAMGR_GetInstance()->RegisterDefaultFeatureApi(EXAMPLE_SERVICE, GET_IUNKNOWN(g_example));
    5. }
  • 定义服务的初始化入口:

    1. SYSEX_SERVICE_INIT(Init);

开发服务的子功能

  • 继承并重新定义功能:

    1. typedefstructDemoFeature{
    2. INHERIT_FEATURE;
    3. INHERIT_IUNKNOWNENTRY(DemoApi);
    4. Identity identity;
    5. Service*parent;
    6. }DemoFeature;
  • 实现功能的生命周期函数:

    1. staticconstchar*FEATURE_GetName(Feature*feature)
    2. {
    3. return EXAMPLE_FEATURE;
    4. }
    5. staticvoid FEATURE_OnInitialize(Feature*feature,Service*parent,Identity identity)
    6. {
    7. DemoFeature*demoFeature =(DemoFeature*)feature;
    8. demoFeature->identity = identity;
    9. demoFeature->parent = parent;
    10. }
    11. staticvoid FEATURE_OnStop(Feature*feature,Identity identity)
    12. {
    13. g_example.identity.queueId = NULL;
    14. g_example.identity.featureId =-1;
    15. g_example.identity.serviceId =-1;
    16. }
    17. static BOOL FEATURE_OnMessage(Feature*feature,Request*request)
    18. {
    19. if(request->msgId == MSG_PROC){
    20. Response response ={.data ="Yes, you did!",.len =0};
    21. SAMGR_SendResponse(request,&response);
    22. return TRUE;
    23. }else{
    24. if(request->msgId == MSG_TIME_PROC){
    25. LOS_Msleep(WAIT_FEATURE_PROC *10);
    26. if(request->msgValue){
    27. SAMGR_PrintServices();
    28. }else{
    29. SAMGR_PrintOperations();
    30. }
    31. AsyncTimeCall(GET_IUNKNOWN(g_example));
    32. return FALSE;
    33. }
    34. }
    35. return FALSE;
    36. }
  • 创建功能对象:

    1. staticDemoFeature g_example ={
    2. .GetName= FEATURE_GetName,
    3. .OnInitialize= FEATURE_OnInitialize,
    4. .OnStop= FEATURE_OnStop,
    5. .OnMessage= FEATURE_OnMessage,
    6. DEFAULT_IUNKNOWN_ENTRY_BEGIN,
    7. .AsyncCall=AsyncCall,
    8. .AsyncTimeCall=AsyncTimeCall,
    9. .SyncCall=SyncCall,
    10. .AsyncCallBack=AsyncCallBack,
    11. DEFAULT_IUNKNOWN_ENTRY_END,
    12. .identity ={-1,-1, NULL},
    13. };
  • 向SAMGR注册功能及接口:

    1. staticvoidInit(void){
    2. SAMGR_GetInstance()->RegisterFeature(EXAMPLE_SERVICE,(Feature*)&g_example);
    3. SAMGR_GetInstance()->RegisterFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE, GET_IUNKNOWN(g_example));
    4. }
  • 定义功能的初始化入口:

    1. SYSEX_FEATURE_INIT(Init);

开发进程内对外接口

  • 定义IUnknown接口:

    1. typedefstructDemoApi{
    2. INHERIT_IUNKNOWN;
    3. BOOL (*AsyncCall)(IUnknown*iUnknown,constchar*buff);
    4. BOOL (*AsyncTimeCall)(IUnknown*iUnknown);
    5. BOOL (*SyncCall)(IUnknown*iUnknown,structPayload*payload);
    6. BOOL (*AsyncCallBack)(IUnknown*iUnknown,constchar*buff,Handler handler);
    7. }DemoApi;
  • 定义IUnknown的引用对象:

    1. typedefstructDemoRefApi{
    2. INHERIT_IUNKNOWNENTRY(DemoApi);
    3. }DemoRefApi;
  • 初始化接口对象:

    1. staticDemoRefApi api ={
    2. DEFAULT_IUNKNOWN_ENTRY_BEGIN,
    3. .AsyncCall=AsyncCall,
    4. .AsyncTimeCall=AsyncTimeCall,
    5. .SyncCall=SyncCall,
    6. .AsyncCallBack=AsyncCallBack,
    7. DEFAULT_IUNKNOWN_ENTRY_END,
    8. };
  • 注册服务接口:

    1. SAMGR_GetInstance()->RegisterFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE, GET_IUNKNOWN(api));

调用进程内服务

  • 获取服务的对外接口:

    1. DemoApi*demoApi = NULL;
    2. IUnknown*iUnknown = SAMGR_GetInstance()->GetFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE);
    3. if(iUnknown == NULL){
    4. return NULL;
    5. }
    6. int result = iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION,(void**)&demoApi);
    7. if(result !=0|| demoApi == NULL){
    8. return NULL;
    9. }
  • 接口调用:

    1. if(demoApi->AsyncCallBack== NULL){
    2. return NULL;
    3. }
    4. demoApi->AsyncCallBack((IUnknown*)demoApi,"I wanna async call callback good result!",AsyncHandler);
  • 释放接口:

    1. int32 ref= demoApi->Release((IUnknown*)demoApi);

开发跨进程间对外接口

  • 继承IServerProxy替代继承IUnknown:INHERIT_SERVER_IPROXY

    1. typedefstructDemoFeatureApi{
    2. INHERIT_SERVER_IPROXY;
    3. BOOL (*AsyncCall)(IUnknown*iUnknown,constchar*buff);
    4. BOOL (*AsyncTimeCall)(IUnknown*iUnknown);
    5. BOOL (*SyncCall)(IUnknown*iUnknown,structPayload*payload);
    6. BOOL (*AsyncCallBack)(IUnknown*iUnknown,constchar*buff,IOwner notify,INotifyFunc handler);
    7. }DemoFeatureApi;
  • 初始化IServerProxy的Invoke函数:

    1. staticDemoFeature g_example ={
    2. SERVER_IPROXY_IMPL_BEGIN,
    3. .Invoke=Invoke,
    4. .AsyncCall=AsyncCall,
    5. .AsyncTimeCall=AsyncTimeCall,
    6. .SyncCall=SyncCall,
    7. .AsyncCallBack=AsyncCallBack,
    8. IPROXY_END,
    9. };
  • 实现Invoke函数来处理Ipc消息:

    1. static int32 Invoke(IServerProxy*iProxy,int funcId,void*origin,IpcIo*req,IpcIo*reply)
    2. {
    3. DemoFeatureApi*api =(DemoFeatureApi*)iProxy;
    4. BOOL ret;
    5. size_t len =0;
    6. switch(funcId){
    7. case ID_ASYNCALL:
    8. ret = api->AsyncCall((IUnknown*)iProxy,(char*)IpcIoPopString(req,&len));
    9. IpcIoPushBool(reply, ret);
    10. break;
    11. case ID_ASYNTIMECALL:
    12. ret = api->AsyncTimeCall((IUnknown*)iProxy);
    13. IpcIoPushBool(reply, ret);
    14. break;
    15. case ID_SYNCCALL:{
    16. structPayload payload;
    17. payload.id =IpcIoPopInt32(req);
    18. payload.value =IpcIoPopInt32(req);
    19. payload.name =(char*)IpcIoPopString(req,&len);
    20. ret = api->SyncCall((IUnknown*)iProxy,&payload);
    21. IpcIoPushString(reply, ret ?"TRUE":"FALSE");
    22. }
    23. break;
    24. case ID_ASYNCCALLBACK:{// convert to sync proxy
    25. IpcIoPushString(reply,"Yes, you did!");
    26. IpcIoPushBool(reply, TRUE);
    27. }
    28. break;
    29. default:
    30. IpcIoPushBool(reply, FALSE);
    31. break;
    32. }
    33. return EC_SUCCESS;
    34. }
  • 注册接口:与进程内接口注册一致

    1. SAMGR_GetInstance()->RegisterFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE, GET_IUNKNOWN(g_example));

调用跨进程间服务

  • 获取跨进程服务的对外接口:

    1. IClientProxy*demoApi = NULL;
    2. IUnknown*iUnknown = SAMGR_GetInstance()->GetFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE);
    3. if(iUnknown == NULL){
    4. return NULL;
    5. }
    6. int result = iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER,(void**)&demoApi);
    7. if(result !=0|| demoApi == NULL){
    8. return NULL;
    9. }
  • 调用Ipc消息接口:

    1. IpcIo request;char data[250];
    2. IpcIoInit(&request, data,sizeof(data),0);
    3. demoApi->Invoke(demoApi,0,&request, NULL, NULL);
  • 释放接口:

    1. int32 ref= demoApi->Release((IUnknown*)demoApi);

开发跨进程间服务调用客户端代理

  • 定义IPC接口客户端代理:

    1. typedefstructDemoClientProxy{
    2. INHERIT_CLIENT_IPROXY;
    3. BOOL (*AsyncCall)(IUnknown*iUnknown,constchar*buff);
    4. BOOL (*AsyncTimeCall)(IUnknown*iUnknown);
    5. BOOL (*SyncCall)(IUnknown*iUnknown,structPayload*payload);
    6. BOOL (*AsyncCallBack)(IUnknown*iUnknown,constchar*buff,IOwner notify,INotifyFunc handler);
    7. }DemoClientProxy;
    8. typedefstructDemoClientEntry{
    9. INHERIT_IUNKNOWNENTRY(DemoClientProxy);
    10. }DemoClientEntry;
  • 实现客户端代理封装Ipc消息接口:

    1. static BOOL AsyncCall(IUnknown*iUnknown,constchar*buff)
    2. {
    3. DemoClientProxy*proxy =(DemoClientProxy*)iUnknown;
    4. IpcIo request;
    5. char data[MAX_DATA_LEN];
    6. IpcIoInit(&request, data, MAX_DATA_LEN,0);
    7. IpcIoPushString(&request, buff);
    8. int ret = proxy->Invoke((IClientProxy*)proxy, ID_ASYNCALL,&request, NULL, NULL);
    9. return ret == EC_SUCCESS;
    10. }
    11. static BOOL AsyncTimeCall(IUnknown*iUnknown)
    12. {
    13. DemoClientProxy*proxy =(DemoClientProxy*)iUnknown;
    14. IpcIo request;
    15. char data[MAX_DATA_LEN];
    16. IpcIoInit(&request, data, MAX_DATA_LEN,0);
    17. int ret = proxy->Invoke((IClientProxy*)proxy, ID_ASYNTIMECALL,&request, NULL, NULL);
    18. return ret == EC_SUCCESS;
    19. }
    20. staticintCallback(IOwner owner,int code,IpcIo*reply)
    21. {
    22. size_t len =0;
    23. return strcpy_s(owner, MAX_DATA_LEN,(char*)IpcIoPopString(reply,&len));
    24. }
    25. static BOOL SyncCall(IUnknown*iUnknown,structPayload*payload)
    26. {
    27. DemoClientProxy*proxy =(DemoClientProxy*)iUnknown;
    28. IpcIo request;
    29. char data[MAX_DATA_LEN];
    30. IpcIoInit(&request, data, MAX_DATA_LEN,0);
    31. IpcIoPushInt32(&request, payload->id);
    32. IpcIoPushInt32(&request, payload->value);
    33. IpcIoPushString(&request, payload->name);
    34. int ret = proxy->Invoke((IClientProxy*)proxy, ID_SYNCCALL,&request, data,Callback);
    35. data[MAX_DATA_LEN -1]=0;
    36. HILOG_INFO(HILOG_MODULE_APP,"[TID:0x%lx]Remote response is %s!", pthread_self(), data);
    37. return ret == EC_SUCCESS;
    38. }
    39. structCurrentNotify{
    40. IOwner notify;
    41. INotifyFunc handler;
    42. };
    43. staticintCurrentCallback(IOwner owner,int code,IpcIo*reply)
    44. {
    45. structCurrentNotify*notify =(structCurrentNotify*)owner;
    46. size_t len =0;
    47. char*response =(char*)IpcIoPopString(reply,&len);
    48. HILOG_INFO(HILOG_MODULE_APP,"[TID:0x%lx]Notify Remote response is %s!", pthread_self(), response);
    49. notify->handler(notify->notify, response);
    50. return EC_SUCCESS;
    51. }
    52. static BOOL AsyncCallBack(IUnknown*iUnknown,constchar*buff,IOwner notify,INotifyFunc handler)
    53. {
    54. structCurrentNotify owner ={notify, handler};
    55. DemoClientProxy*proxy =(DemoClientProxy*)iUnknown;
    56. IpcIo request;
    57. char data[MAX_DATA_LEN];
    58. IpcIoInit(&request, data, MAX_DATA_LEN,0);
    59. IpcIoPushString(&request, buff);
    60. int ret = proxy->Invoke((IClientProxy*)proxy, ID_ASYNCCALLBACK,&request,&owner,CurrentCallback);
    61. return ret == EC_SUCCESS;
    62. }
  • 实现客户端代理的工厂方法:

    1. void*DEMO_CreatClient(constchar*service,constchar*feature, uint32 size)
    2. {
    3. (void)service;
    4. (void)feature;
    5. uint32 len = size +sizeof(DemoClientEntry);
    6. uint8 *client = malloc(len);
    7. (void)memset_s(client, len,0, len);
    8. DemoClientEntry*entry =(DemoClientEntry*)&client[size];
    9. entry->ver =((uint16)CLIENT_PROXY_VER |(uint16)DEFAULT_VERSION);
    10. entry->ref=1;
    11. entry->iUnknown.QueryInterface= IUNKNOWN_QueryInterface;
    12. entry->iUnknown.AddRef= IUNKNOWN_AddRef;
    13. entry->iUnknown.Release= IUNKNOWN_Release;
    14. entry->iUnknown.Invoke= NULL;
    15. entry->iUnknown.AsyncCall=AsyncCall;
    16. entry->iUnknown.AsyncTimeCall=AsyncTimeCall;
    17. entry->iUnknown.SyncCall=SyncCall;
    18. entry->iUnknown.AsyncCallBack=AsyncCallBack;
    19. return client;
    20. }
    21. void DEMO_DestroyClient(constchar*service,constchar*feature,void*iproxy)
    22. {
    23. free(iproxy);
    24. }
  • 将客户端代理的工厂方法注册到SAMGR:

    1. SAMGR_RegisterFactory(EXAMPLE_SERVICE, EXAMPLE_FEATURE, DEMO_CreatClient, DEMO_DestroyClient);
  • 获取跨进程服务的对外接口:

    1. DemoClientProxy*demoApi = NULL;
    2. IUnknown*iUnknown = SAMGR_GetInstance()->GetFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE);
    3. if(iUnknown == NULL){
    4. return NULL;
    5. }
    6. int result = iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION,(void**)&demoApi);
    7. if(result !=0|| demoApi == NULL){
    8. return NULL;
    9. }
  • 调用跨进程服务的客户端代理接口:

    1. if(demoApi->AsyncCallBack== NULL){
    2. return NULL;
    3. }
    4. demoApi->AsyncCallBack((IUnknown*)demoApi,
    5. "I wanna async call callback good result!", NULL,AsyncHandler);
  • 释放接口:

    1. int32 ref= demoApi->Release((IUnknown*)demoApi);

涉及仓

distributedschedule_interfaces_innerkits_samgr_lite

distributedschedule_services_samgr_lite