В связи с ограниченными ресурсами платформы предлагается унифицированный фреймворк системных возможностей, который гармонизирует различия архитектур аппаратных средств (например, RISC-V, Cortex-M и Cortex-A), ресурсов платформы и режимов выполнения. Определяются два типа аппаратных платформ (M- и A-ядра).
Этот сервисно-ориентированный фреймворк системных возможностей позволяет разрабатывать сервисы, функции и внешние API, а также реализовывать многопроцессное взаимодействие и вызовы сервисов для межпроцессного взаимодействия (IPC).- M-ядро предоставляет сервисы, функции, внешние API и разработку многопроцессного взаимодействия.
Рис. 1 Сервисно-ориентированная архитектура
Рис. 2 Основные объекты фреймворка системных возможностей
Рис. 1 Структура директории исходного кода фреймворка системных возможностей| Имя | Описание | | -------------------------------------------------- | -------------------------------------------- | | interfaces/kits/samgr_lite/samgr | Внешние API фреймворков системных возможностей M- и A-ядра. | | interfaces/kits/samgr_lite/registry | Внешние API для вызова служб между процессами A-ядра. | | interfaces/kits/samgr_lite/communication/broadcast | Внешние API службы рассылки событий внутри процессов M- и A-ядра. | | services/samgr_lite/samgr/adapter | Слой адаптации POSIX и CMSIS интерфейсов, используемый для гармонизации различий между API M- и A-ядра.| | services/samgr_lite/samgr/registry | Stub-функции для регистрации и обнаружения служб M-ядра. | | services/samgr_lite/samgr/source | Основной код фреймворков системных возможностей M- и A-ядра. | | services/samgr_lite/samgr_client | Регистрация и обнаружение для вызова служб между процессами A-ядра. | | services/samgr_lite/samgr_server | Управление адресами IPC и контроль доступа для вызова служб между процессами A-ядра. | | services/samgr_lite/samgr_endpoint | Управление приемом и передачей пакетов для IPC A-ядра. | | services/samgr_lite/communication/broadcast | Служба рассылки событий для процессов M- и A-ядра. |## Ограничения
Наследуйте и переопределяйте сервис.
typedef struct ExampleService {
INHERIT_SERVICE;
INHERIT_IUNKNOWNENTRY(DefaultFeatureApi);
Identity identity;
} ExampleService;
Реализуйте функции жизненного цикла сервиса.
static const char *GetName(Service *service)
{
return EXAMPLE_SERVICE;
}
static BOOL Initialize(Service *service, Identity identity)
{
ExampleService *example = (ExampleService *)service;
// Сохраните уникальный идентификатор сервиса, который используется при использовании IUnknown для отправки сообщений сервису.
example->identity = identity;
return TRUE;
}
static BOOL MessageHandle(Service *service, Request *msg)
{
ExampleService *example = (ExampleService *)service;
switch (msg->msgId) {
case MSG_SYNC:
// Обрабатывайте сервис.
break;
default:break;
}
return FALSE;
}
static TaskConfig GetTaskConfig(Service *service)
{
TaskConfig config = {LEVEL_HIGH, PRI_BELOW_NORMAL,
0x800, 20, SHARED_TASK};
return config;
}
```- Создайте объект сервиса.
static ExampleService g_example = { .GetName = GetName, .Initialize = Initialize, .MessageHandle = MessageHandle, .GetTaskConfig = GetTaskConfig, SERVER_IPROXY_IMPL_BEGIN, .Invoke = NULL, .SyncCall = SyncCall, IPROXY_END, };
Зарегистрируйте сервис и API с Samgr.
static void Init(void)
{
SAMGR_GetInstance()->RegisterService((Service *)&g_example);
SAMGR_GetInstance()->RegisterDefaultFeatureApi(EXAMPLE_SERVICE, GET_IUNKNOWN(g_example));
}
Определите инициализатор сервиса.
SYSEX_SERVICE_INIT(Init);
Наследуйте и переопределяйте функцию.
typedef struct DemoFeature {
INHERIT_FEATURE;
INHERIT_IUNKNOWNENTRY(DemoApi);
Identity identity;
Service *parent;
} DemoFeature;
Реализуйте функции жизненного цикла функции.
```c
static const char *FEATURE_GetName(Feature *feature)
{
return EXAMPLE_FEATURE;
}
static void FEATURE_OnInitialize(Feature *feature, Service *parent, Identity identity)
{
DemoFeature *demoFeature = (DemoFeature *)feature;
demoFeature->identity = identity;
demoFeature->parent = parent;
}
static void FEATURE_OnStop(Feature *feature, Identity identity)
{
g_example.identity.queueId = NULL;
g_example.identity.featureId = -1;
g_example.identity.serviceId = -1;
}
static BOOL FEATURE_OnMessage(Feature *feature, Request *request)
{
if (request->msgId == MSG_PROC) {
Response response = {.data = "Да, вы это сделали!", .len = 0};
SAMGR_SendResponse(request, &response);
return TRUE;
} else {
if (request->msgId == MSG_TIME_PROC) {
LOS_Msleep(WAIT_FEATURE_PROC * 10);
if (request->msgValue) {
SAMGR_PrintServices();
} else {
SAMGR_PrintOperations();
}
AsyncTimeCall(GET_IUNKNOWN(g_example));
return FALSE;
}
}
return FALSE;
}
Создайте объект функции. ``` static DemoFeature g_example = { .GetName = FEATURE_GetName, .OnInitialize = FEATURE_OnInitialize, .OnStop = FEATURE_OnStop, .OnMessage = FEATURE_OnMessage, DEFAULT_IUNKNOWN_ENTRY_BEGIN, .AsyncCall = AsyncCall, .AsyncTimeCall = AsyncTimeCall, .SyncCall = SyncCall, .AsyncCallBack = AsyncCallBack, DEFAULT_IUNKNOWN_ENTRY_END, .identity = {-1, -1, NULL}, };
Зарегистрируйте функцию и API с Samgr.
static void Init(void){
SAMGR_GetInstance()->RegisterFeature(EXAMPLE_SERVICE, (Feature *)&g_example);
SAMGR_GetInstance()->RegisterFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE, GET_IUNKNOWN(g_example));
}
Определите инициализатор функции.
SYSEX_FEATURE_INIT(Init);
Определите API IUnknown.
typedef struct DemoApi {
INHERIT_IUNKNOWN;
BOOL (*AsyncCall)(IUnknown *iUnknown, const char *buff);
BOOL (*AsyncTimeCall)(IUnknown *iUnknown);
BOOL (*SyncCall)(IUnknown *iUnknown, struct Payload *payload);
BOOL (*AsyncCallBack)(IUnknown *iUnknown, const char *buff, Handler handler);
} DemoApi;
Определите объект-ссылку IUnknown.
typedef struct DemoRefApi {
INHERIT_IUNKNOWNENTRY(DemoApi);
} DemoRefApi;
Инициализируйте объект IUnknown.
static DemoRefApi api = {
DEFAULT_IUNKNOWN_ENTRY_BEGIN,
.AsyncCall = AsyncCall,
.AsyncTimeCall = AsyncTimeCall,
.SyncCall = SyncCall,
.AsyncCallBack = AsyncCallBack,
DEFAULT_IUNKNOWN_ENTRY_END,
};
Зарегистрируйте функциональный API.
SAMGR_GetInstance()->RegisterFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE, GET_IUNKNOWN(api));
Получите внешний API сервиса. ``` DemoApi *demoApi = NULL; IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE); if (iUnknown == NULL) { return NULL; } int result = iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void **)&demoApi); if (result != 0 || demoApi == NULL) { return NULL; }
if (demoApi->AsyncCallBack == NULL) { return NULL; } demoApi->AsyncCallBack((IUnknown *)demoApi, "Я хочу асинхронный вызов обратного вызова с хорошим результатом!", AsyncHandler);
Освободите API.
int32 ref = demoApi->Release((IUnknown *)demoApi);
Наследуйте IServerProxy для замены IUnknown: INHERIT_SERVER_IPROXY
typedef struct DemoFeatureApi {
INHERIT_SERVER_IPROXY;
BOOL (*AsyncCall)(IUnknown *iUnknown, const char *buff);
BOOL (*AsyncTimeCall)(IUnknown *iUnknown);
BOOL (*SyncCall)(IUnknown *iUnknown, struct Payload *payload);
BOOL (*AsyncCallBack)(IUnknown *iUnknown, const char *buff, IOwner notify, INotifyFunc handler);
} DemoFeatureApi;
Инициализируйте объект IServerProxy.
static DemoFeature g_example = {
SERVER_IPROXY_IMPL_BEGIN,
.Invoke = Invoke,
.AsyncCall = AsyncCall,
.AsyncTimeCall = AsyncTimeCall,
.SyncCall = SyncCall,
.AsyncCallBack = AsyncCallBack,
IPROXY_END,
};
```- Реализуйте функцию **Invoke** для обработки сообщений IPC.```diff
static int32 Вызвать(IServerProxy *iProxy, int funcId, void *origin, IpcIo *req, IpcIo *ответ) { DemoFeatureApi *api = (DemoFeatureApi *)iProxy; BOOL ret; size_t len = 0; switch (funcId) { case ID_ASYNCALL: ret = api->AsyncCall((IUnknown *)iProxy, (char *)IpcIoPopString(req, &len)); IpcIoPushBool(ответ, ret); break; case ID_ASYNTIMECALL: ret = api->AsyncTimeCall((IUnknown *)iProxy); IpcIoPushBool(ответ, ret); break; case ID_SYNCCALL: { struct Payload payload; payload.id = IpcIoPopInt32(req); payload.value = IpcIoPopInt32(req); payload.name = (char *)IpcIoPopString(req, &len); ret = api->SyncCall((IUnknown *)iProxy, &payload); IpcIoPushString(ответ, ret ? "TRUE" : "FALSE"); } break; case ID_ASYNCCALLBACK: { // конвертировать в синхронный прокси IpcIoPushString(ответ, "Да, вы это сделали!"); IpcIoPushBool(ответ, TRUE); } break; default: IpcIoPushBool(ответ, FALSE); break; } return EC_SUCCESS; }
```diff
- Реализуйте функцию **Invoke** для обработки сообщений IPC.
```diff
static int32 Вызвать(IServerProxy *iProxy, int funcId, void *origin, IpcIo *req, IpcIo *ответ)
{
DemoFeatureApi *api = (DemoFeatureApi *)iProxy;
BOOL ret;
size_t len = 0;
switch (funcId) {
case ID_ASYNCALL:
ret = api->AsyncCall((IUnknown *)iProxy, (char *)IpcIoPopString(req, &len));
IpcIoPushBool(ответ, ret);
break;
case ID_ASYNTIMECALL:
ret = api->AsyncTimeCall((IUnknown *)iProxy);
IpcIoPushBool(ответ, ret);
break;
case ID_SYNCCALL: {
struct Payload payload;
payload.id = IpcIoPopInt32(req);
payload.value = IpcIoPopInt32(req);
payload.name = (char *)IpcIoPopString(req, &len);
ret = api->SyncCall((IUnknown *)iProxy, &payload);
IpcIoPushString(ответ, ret ? "TRUE" : "FALSE");
}
break;
case ID_ASYNCCALLBACK: { // конвертировать в синхронный прокси
IpcIoPushString(ответ, "Да, вы это сделали!");
IpcIoPushBool(ответ, TRUE);
}
break;
default:
IpcIoPushBool(ответ, FALSE);
break;
}
return EC_SUCCESS;
}
```- Зарегистрируйте API. Этот шаг аналогичен регистрации API для внутрисистемной коммуникации. ```
SAMGR_GetInstance()->RegisterFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE, GET_IUNKNOWN(g_example));
```
## Вызов сервиса в другом процессе
- Получите внешний API сервиса в другом процессе.
```
IClientProxy *demoApi = NULL;
IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE);
if (iUnknown == NULL) {
return NULL;
}
int result = iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, (void **)&demoApi);
if (result != 0 || demoApi == NULL) {
return NULL;
}
```
- Вызовите API для отправки сообщений IPC.
```
IpcIo request;
char data[250];
IpcIoInit(&request, data, sizeof(data), 0);
demoApi->Invoke(demoApi, 0, &request, NULL, NULL);
```
- Освободите API.
```
int32 ref = demoApi->Release((IUnknown *)demoApi);
```
## Разработка клиентского прокси для вызова сервиса между процессами
- Определите клиентский прокси для API IPC.
```
typedef struct DemoClientProxy {
INHERIT_CLIENT_IPROXY;
BOOL (*AsyncCall)(IUnknown *iUnknown, const char *buff);
BOOL (*AsyncTimeCall)(IUnknown *iUnknown);
BOOL (*SyncCall)(IUnknown *iUnknown, struct Payload *payload);
BOOL (*AsyncCallBack)(IUnknown *iUnknown, const char *buff, IOwner notify, INotifyFunc handler);
} DemoClientProxy;
typedef struct DemoClientEntry {
INHERIT_IUNKNOWNENTRY(DemoClientProxy);
} DemoClientEntry;
```- Активируйте клиентский прокси для упаковки API сообщений IPC.
```markdown
```
static BOOL AsyncCall(IUnknown *iUnknown, const char *buff)
{
DemoClientProxy *proxy = (DemoClientProxy *)iUnknown;
IpcIo request;
char data[MAX_DATA_LEN];
IpcIoInit(&request, data, MAX_DATA_LEN, 0);
IpcIoPushString(&request, buff);
int ret = proxy->Invoke((IClientProxy *)proxy, ID_ASYNCALL, &request, NULL, NULL);
return ret == EC_SUCCESS;
}
static BOOL AsyncTimeCall(IUnknown *iUnknown)
{
DemoClientProxy *proxy = (DemoClientProxy *)iUnknown;
IpcIo request;
char data[MAX_DATA_LEN];
IpcIoInit(&request, data, MAX_DATA_LEN, 0);
int ret = proxy->Invoke((IClientProxy *)proxy, ID_ASYNTIMECALL, &request, NULL, NULL);
return ret == EC_SUCCESS;
}
static int Callback(IOwner owner, int code, IpcIo *reply)
{
size_t len = 0;
return strcpy_s(owner, MAX_DATA_LEN, (char *)IpcIoPopString(reply, &len));
}
static BOOL SyncCall(IUnknown *iUnknown, struct Payload *payload)
{
DemoClientProxy *proxy = (DemoClientProxy *)iUnknown;
IpcIo request;
char data[MAX_DATA_LEN];
IpcIoInit(&request, data, MAX_DATA_LEN, 0);
IpcIoPushInt32(&request, payload->id);
IpcIoPushInt32(&request, payload->value);
IpcIoPushString(&request, payload->name);
int ret = proxy->Invoke((IClientProxy *)proxy, ID_SYNCCALL, &request, data, Callback);
data[MAX_DATA_LEN - 1] = 0;
HILOG_INFO(HILOG_MODULE_APP, "[TID:0x%lx]Remote response is %s! ", pthread_self(), data);
return ret == EC_SUCCESS;
}
struct CurrentNotify {
IOwner notify;
INotifyFunc handler;
};
static int CurrentCallback(IOwner owner, int code, IpcIo *reply)
{
struct CurrentNotify *notify = (struct CurrentNotify *)owner;
size_t len = 0;
char *response = (char *)IpcIoPopString(reply, &len);
HILOG_INFO(HILOG_MODULE_APP, "[TID:0x%lx]Notify Remote response is %s! ", pthread_self(), response);
notify->handler(notify->notify, response);
return EC_SUCCESS;
}
static BOOL AsyncCallBack(IUnknown *iUnknown, const char *buff, IOwner notify, INotifyFunc handler)
{
``` struct CurrentNotify owner = {notify, handler};
DemoClientProxy *proxy = (DemoClientProxy *)iUnknown;
IpcIo request;
char data[MAX_DATA_LEN];
``` IpcIoInit(&request, data, MAX_DATA_LEN, 0);
IpcIoPushString(&request, buff);
int ret = proxy->Invoke((IClientProxy *)proxy, ID_ASYNCCALLBACK, &request, &owner, CurrentCallback);
return ret == EC_SUCCESS;
}
```- Реализуйте фабричный метод для создания прокси-клиента. ```
void *DEMO_CreatClient(const char *service, const char *feature, uint32 size)
{
(void)service;
(void)feature;
uint32 len = size + sizeof(DemoClientEntry);
uint8 *client = malloc(len);
(void)memset_s(client, len, 0, len);
DemoClientEntry *entry = (DemoClientEntry *)&client[size];
entry->ver = ((uint16)CLIENT_PROXY_VER | (uint16)DEFAULT_VERSION);
entry->ref = 1;
entry->iUnknown.QueryInterface = IUNKNOWN_QueryInterface;
entry->iUnknown.AddRef = IUNKNOWN_AddRef;
entry->iUnknown.Release = IUNKNOWN_Release;
entry->iUnknown.Invoke = NULL;
entry->iUnknown.AsyncCall = AsyncCall;
entry->iUnknown.AsyncTimeCall = AsyncTimeCall;
entry->iUnknown.SyncCall = SyncCall;
entry->iUnknown.AsyncCallBack = AsyncCallBack;
return client;
}
void DEMO_DestroyClient(const char *service, const char *feature, void *iproxy)
{
free(iproxy);
}
```
- Зарегистрируйте фабричный метод прокси-клиента в Samgr.
```
SAMGR_RegisterFactory(EXAMPLE_SERVICE, EXAMPLE_FEATURE, DEMO_CreatClient, DEMO_DestroyClient);
```
- Получите внешний API службы в другом процессе.
```
DemoClientProxy *demoApi = NULL;
IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE);
if (iUnknown == NULL) {
return NULL;
}
int result = iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void **)&demoApi);
if (result != 0 || demoApi == NULL) {
return NULL;
}
```
- Вызовите API прокси-клиента службы в другом процессе.
```
if (demoApi->AsyncCallBack == NULL) {
return NULL;
}
demoApi->AsyncCallBack((IUnknown *)demoApi,
"Хочу асинхронный вызов обратного вызова с хорошим результатом!", NULL, AsyncHandler);
```
- Освободите API.
```
int32 ref = demoApi->Release((IUnknown *)demoApi);
```
## Вовлечённые репозитории
Samgr
[**systemabilitymgr\_samgr\_lite**](https://gitee.com/openharmony/systemabilitymgr_samgr_lite)[systemabilitymgr_samgr](https://gitee.com/openharmony/systemabilitymgr_samgr)[systemabilitymgr_safwk](https://gitee.com/openharmony/systemabilitymgr_safwk)
[systemabilitymgr_safwk_lite](https://gitee.com/openharmony/systemabilitymgr_safwk_lite)
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )