往期知识点记录:
- 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总
- OpenHarmony轻量系统服务管理|鸿蒙业务模型重要概念详解
- OpenHarmony轻量系统服务管理|同进程及跨进程间通信的数据结构及过程详解
- OpenHarmony轻量系统服务管理|系统服务间调用之对外接口详解
- OpenHarmony轻量系统服务管理|系统服务管理之基础框架及功能详解
- OpenHarmony轻量系统服务管理|系统服务管理之系统功能管理器详解
- OpenHarmony轻量系统服务管理|消息广播服务及其子功能详解
- OpenHarmony轻量系统服务管理|消息广播功能实例操作详解(一)
- OpenHarmony轻量系统服务管理|消息广播功能实例操作详解(二)
- OpenHarmony POSIX和CMSIS接口适配层解读(1):queue_adapter
- OpenHarmony POSIX和CMSIS接口适配层解读adapter(2):thread/memory/time
- OpenHarmony轻量系统服务管理-samgr主要接口思维导图(1)
- OpenHarmony轻量系统服务管理-samgr主要接口思维导图(2)
- OpenHarmony轻量系统服务管理-samgr:common赏析及实现
- OpenHarmony轻量系统服务管理-samgr:iunknown赏析
- OpenHarmony轻量系统服务管理-samgr:iunknown实现分析
- OpenHarmony轻量系统服务管理samgr-message赏析
- 持续更新中……
一、前言
OpenHarmony在Samgr的message
设计中,提供了一些支持消息通信的API,通过这些API可以实现IUnknown
的异步函数功能。message
的声明在distributedschedule_samgr_lite\interfaces\kits\samgr\message.h
中,本文将对其中的结构体、宏定义、函数声明等进行分析。
二、头文件分析
- 结构体分析
//当前文件中声明的结构体将用于消息交互,所以需要通知编译器进行内存对齐
//在本文最后一部分对内存对齐进行了讲解
#pragma pack(1)//以单字节对齐
/*
可以使用此结构来标识一个IUnknown特性,消息将通过IUnknown的异步函数发送到该特性。
*/
struct Identity {
//服务ID
int16 serviceId; //开发服务时,需要实现服务的生命周期接口
//特性ID
int16 featureId; //开发功能时,需要实现功能的生命周期接口
//消息队列ID
MQueueId queueId; //消息队列标识
};
//定义一个请求
//通过异步函数IUnknown发送到特性的请求
struct Request {
int16 msgId; //消息ID
int16 len; //数据长度
void *data; //数据字段
uint32 msgValue; //消息值
};
//定义一个响应
//此结构用于在服务的消息处理功能之后发送响应
struct Response {
//数据段
void *data;
//数据长度
int16 len;
};
#pragma pack()//优化内存对齐结束
- 函数声明分析
//声明一个处理异步响应的函数指针
typedef void (*Handler)(const Request *request, const Response *response);
/*
向指定标识的服务或特性发送请求
@identity处理消息的特性或服务的标识指针。
@request指向请求的指针。
@handler处理响应的函数。如果值为NULL,则不响应。
*/
int32 SAMGR_SendRequest(const Identity *identity, const Request *request, Handler handler);
/*
向多个服务或特性发送请求以节省内存。
@identity请求所指向的服务或特性id的指针被发送。
@request指向请求的指针。
@token引用计数指针。
@handler处理响应的函数。如果值NULL,不需要响应。
*/
uint32 *SAMGR_SendSharedRequest(const Identity *identity, const Request *request, uint32 *token, Handler handler);
/*
向特性线程发送调用者的请求和响应。每次调用此函数时,引用计数的值加1
@id请求和响应发送到的服务或特性的id指针。
@request指向请求的指针。
@respp响应指针。
@ref引用计数。
@handler处理请求和响应的函数。这个参数不能是NULL。
*/
int32 SAMGR_SendSharedDirectRequest(const Identity *id, const Request *req, const Response *resp, uint32 **ref,Handler handler);
/*
处理请求后发送响应。
@request指向原始请求的指针。
@response指向响应内容的指针。
*/
int32 SAMGR_SendResponse(const Request *request, const Response *response);
/*
在处理原始请求后向指定的服务或特性发送响应
@id指向服务或特性id的指针。响应被发送到服务或特性的线程进行处理。
@request指向原始请求的指针。
@response指向响应内容的指针。
*/
int32 SAMGR_SendResponseByIdentity(const Identity *id, const Request *request, const Response *response);
三、内存对齐
编译器在默认情况下会对结构体进行内存对齐,内存对齐的规则一般如下:
1.结构体的第一个成员放在偏移量为0的地址处。
2.结构体的其他成员要在对齐数的整数倍的地址处。对齐数 = 编译器默认的一个对齐数与该成员大小中的较小值。VS中默认值是8,Linux默认值为4。
3.结构体总大小为最大对齐数的整数倍。
内存对齐有什么作用?这里涉及到内存边界问题,它们的地址分别是可被2/4/8整除的。如果数据在地址上随意的存放,那么数据可能会存储在某个内存边界上。当CPU读取这个数据时,第一次获取了前半段,发现数据不完整,会再发起一次操作,读取下半段。这样就会导致读取一条数据需要二次或者更多的操作。而内存对齐的好处就在于数据可以被一次操作读取完成就不会发生第二次读取操作,这样就减少了CPU的工作,提高效率。如下图,读取a需要两次,读取b只需要一次。
写在最后
如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
- 想要获取更多完整鸿蒙最新学习资源,请看下图提示: