当前位置:首页 > 公众号精选 > 嵌入式大杂烩
[导读]本来今晚想写如何搞动态加载和动态补丁的,但很不幸,翻遍了硬盘,也没找到以前的代码,连网盘里都没备份。这时候,才焕然大悟--半年前我换上现在的笔记本,淘汰了那台老掉牙的台式机。所幸硬盘没丢,不过一时时也没法读里面的数据了。等过些日子,读出里面的数据再谈动态加载和动态补丁技术。今天说些简单的,能在软件设计中立即用得上的,模块间通信技术--统一消息。

点击上方「嵌入式大杂烩」,选择「置顶公众号」第一时间查看嵌入式笔记!

链接:https://www.cnblogs.com/hhao020/p/5018951.html

本来今晚想写如何搞动态加载和动态补丁的,但很不幸,翻遍了硬盘,也没找到以前的代码,连网盘里都没备份。这时候,才焕然大悟--半年前我换上现在的笔记本,淘汰了那台老掉牙的台式机。

所幸硬盘没丢,不过一时时也没法读里面的数据了。等过些日子,读出里面的数据再谈动态加载和动态补丁技术。今天说些简单的,能在软件设计中立即用得上的,模块间通信技术--统一消息。

统一消息模型,最早的启发是UT的Wacos SSI。那是一个很不错的通信模型,允许模块间的通信统一成队列通信;而在物理上,模块可能位于各种网络中的不同的实体,又或者是不同的进程,线程。

记得那会调试核心网的程序,在板卡上是没有什么调试环境的,除了WindShell(同CSHELL)外,就没什么支撑了。

于是我们就把软件用GDB加载到目标机(无盘工作站),然后开始测试。有人不理解了,这没啥啊!现实是这价值很大,大型系统的嵌入式开发,能争取到的机房空间、设备和板卡总是奇缺,就当时的情况来说,我们三四个人才能分到一套设备。

Wacos_SSI的队列通信技术,让我们可以把目标机做成功能板块,且只需要极少量的修改,就能和实际系统的主控板进行通讯联测,工作效率的提升自不待言。

再后来,哥在Nortel的时候知道了TIPC协议,好象是E///和IBM捣腾出来的东西。思路上,和Wacos SSI很接近。所不同的是,Wacos SSI在消息头里使用了IP地址,而TIPC则是自定义的节点地址,也因此包含了一个额外的节点地址和特定网络间的地址翻译过程。

另外一个区别是,Wacos SSI考虑了远程节点间通信和本地通信的差别,只有远程通信时才传递消息实体,而本地则是传递标识(Handle)来快速完成。TIPC则没讲述这个层次的程序设计问题,也因此在工程实践中应用寥寥。

现如今,UT没了,Nortel也没了。特别是UT,十多年过去了,哥特别怀念那段日子,和我的那个团队。无奈,哥就是灾星,跟喜欢的公司相克。很多局外人都说UT不咋的,就一个做小灵通的;可哥的眼里,那的许多软件开发团队,战斗力一点不比Huawei差。

就说哥做的网关城域交换机,才十来个人,而huawei是几十人,好几倍啊,最后市场表现还是平分秋色。当然,我还是蛮佩服huawei的,他们的东西真心做的漂亮,维护界面人性化,不像我们的,很多事情要命令行来实现。不过我们也有特点,就是架构做的非常好,以至于客户的需求,总是能很快实现,而且基本上对现有功能是0风险。呵呵,据说气死不少人!

这当中,有三大功臣:

  • Wacos SSI;
  • 状态机;
  • 数据驱动模型。

状态机的代码,已经在昨晚的内存泄漏里的链接里提供了,有兴趣可以下载或是用在喜欢的地方,哥只希望它有更多机会发挥价值。

嗯,Wacos SSI排在第一!是的,Wacos SSI的消息通信让我们的系统变得非常柔性,模块与模块间几乎没有什么复杂的耦合。想想现在那些公司招聘需求里,要求什么多任务多线程编程能力,精通什么信号量和同步技术,哥就想哭,这就是我们的软件水平,时刻准备着处在玩死自己。

哥做程序,只考虑CPU有几个线程核,至于系统有几个进程线程,都是这个决定的,而且合并拆解任务,都是分分钟能改代码实现的事。

跟哥一起做软件,就只要记住几点:无论你和谁通信,你只要知道他的地址,然后发消息给他就好了;而你也只要看着自己的队列,有消息就干活,没消息就歇着。

至于发消息,就一个标准的函数,而消息封装格式,也是统一的。至于系统函数库里提供的什么信号量,管道啥的,千万别尝试在应用里面使用,否则,编译器会用编译错误来告诉你行不通。

有点扯远了,回到正题。

统一消息的定义,包含两个部分,消息标签和消息头,具体如下:

typedef struct _MSG_TAG_TYPE_
{

zAddr_t srcAddr;
zAddr_t dstAddr;
zHandle_t msgHandle;
} PACKED zMsg_t;

typedef struct _MSG_HEAD_TYPE_
{

byte_t sysrsvd[8]; //reserved for adding src & dst addresses on network. 
word_t msgLen;
word_t msgId; 
dword_t srcInst;
dword_t dstInst;
} PACKED zMsgHdr_t;

typedef struct _MSG_HEAD_EX_TYPE_
{

zAddr_t srcAddr;
zAddr_t dstAddr; 
word_t msgLen;
word_t msgId; 
dword_t srcInst;
dword_t dstInst;
byte_t msgBuf[1];
} PACKED zMsgHdrEx_t;

zMsg_t结构是消息标签,应用程序收、发消息时,都是收发的这个数据结构,如下:

int zMsgSend(zMsg_t *msg);

通常来说,我们应该把这个消息标签做的比较小,因为做的太大,来回复制它的内容是需要耗费CPU时间的。比如,你可以将zAddr_t定义成word,zHandle_t定义成dword,这样只需要8字节就够了。不过记得字节对齐,一般来说,要保证长度是4的倍数。

消息头就是消息内容的头部格式段,除了这个头部,剩下的就是应用自定义的payload部分。zMsgHdr_t和zMsgHdrEx_t实质上是一样的。这里面的地址部分,不是必须的,只有当消息透过网络或是总线传递时,才是必须的,否则没法由边界模块还原。而对于应用,如无特别约定,那几个字节是无意义且内容不确定的。

消息标签和消息间是通过msgHandle关联。这样,当消息在本地传递时,msgHandle指向的是一块普通内存;而当消息在本地进程间通信时,则指向共享内存;至于网络或是某个总线传递,边界模块负责本地内存数据和网络数据间的转换。如此一来,最大程度的减少实际消息体的拷贝开销,让消息传递变得高效,且细节处理对应用透明。

Wacos SSI的地址部分,填的是IP地址;当然,它还定义了一个模块号来配合这个地址使用。整个通信过程很简单,应用只需要申请一个队列,并告知SSI,这个队列和哪个目的模块号使用。

正常情况下,这个做法都能满足需求,但碰上程序模块重新规划或是特俗测试目的,就有点力不从心了。因此,哥在zMsg_t标签里彻底放弃了IP+module的地址组成,改为TIPC的地址方式。不过这也就让系统必须维护一个路由表,用来完成特定目的地址到队列的映射。

统一消息路由表定义如下:

typedef struct Z_UDP_ADDR_TYPE
{
dword_t ip;
word_t port;
} zUDPAddr_t;
typedef struct Z_MSGQ_ADDR_TYPE
{
void *qid;
} zQueAddr_t;

typedef struct Z_MSGQ_OUT_TYPE
{
zAddr_t addr; 
zUDPAddr_t udpAddr;
zQueAddr_t queAddr; 
} zMsgRoute_t;

路由表项里首先是地址,对应的是消息的目的地址。接下来是网络地址和队列地址,可以有一个或是都有。

  • 仅队列地址:说明是本地(或者是需要经隐形边界代理转发)的消息,目的地址为队列所有者;
  • 仅网络地址:说明是远程消息,且应该直接网络发送,无需经过边界代理,目的地址为远端模块地址;
  • 含两类地址:远程消息,应用发送时通过队列地址送入边界模块,再通过网络地址发送,,目的地址为远端模块地址。

总上面的关系可以看出,队列和地址间的关系是一对多的关系,即多个地址的消息可能被投送到同一个队列。

这就让模块合并变得异常容易,当然,不安规则出牌的模块什么时候什么方法都白搭。通常来说,如果有IP网络的通信要求,系统就需要创建一个基础的网络边界模块。

这个模块本身可能并不需要地址,而只需要提供一个消息聚合的队列。当然,在一个开放的网络环境下,这个边界模块可能还需要做些安全性的工作,比如过滤非法消息等,这可以通过在模块内额外配置源IP地址,端口或是源目的地址等实现。

如果远端并不支持zMsg_t工作,则这时候的边界模块就需要做好消息的翻译过程,为远端模块分配映射模块地址。当然,这些都是本地的,不属于路由表内容。

从地址映射到真实的目的队列或是网络地址,是个频繁的操作,设计上必须要非常高效。对于地址非常少的系统,比如总共才七八个模块,可以用一个紧凑的数据来做,简单且不妨碍效率。但对于有数十或是上百个地址的系统来说,遍历方法就不可取了。这时应该用二分搜索,或是平衡二叉树。

比如城域交换机,有十来块子功能卡,每张卡上有十来个模块,整个系统的地址空间有一百多,采用二分搜索,最多8次就够了!相比消息处理函数的指令数,这部分开销完全可以接受。而从另一个角度来说,统一消息让程序变得简单可控,系统内减少了消息的拷贝操作,所带来的系统效率和性能提升,远远大于查询路由表的开销。

当嵌入式世界有了统一消息后,哪些多线程的开发技巧还有很大价值么?一般应用开发者真的需要理解这些知识么?

温馨提示

由于微信公众号近期改变了推送规则,如果您想经常看到我们的文章,可以在每次阅读后,在页面下方点一个「赞」或「在看」,这样每次推送的文章才会第一时间出现在您的订阅列表里。

版权声明:本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。


猜你喜欢:

实践 | AP3216三合一整合型光感测器实验分享

实用 | 一个高性能通信库的简单使用分享

不按套路出牌,这么来写IIC驱动?

干货 | C语言实现面向对象编程(附代码)

2020年精选原创笔记汇总

在公众号聊天界面回复1024,可获取嵌入式资源;回复 ,可查看文章汇总。

文章都看完了不点个吗

免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

2024年4月11日,中国——意法半导体的ST25R100近距离通信(NFC)读取器芯片独步业界,集先进的技术功能、稳定可靠的通信连接和低廉的成本价格于一身,在大规模制造的消费电子和工控设备内,可以提高非接触式互动功能的...

关键字: 嵌入式 数据读取器 芯片

单片机是一种嵌入式系统,它是一块集成电路芯片,内部包含了处理器、存储器和输入输出接口等功能。

关键字: 单片机 编写程序 嵌入式

深圳2024年4月23日 /美通社/ -- 全球AI解决方案与工业级存储领导品牌宜鼎国际 (Innodisk)持续深化边缘AI布局,今(23)日发表全球首创"MIPI over Type-C"独家技术,让旗下嵌入式相机模...

关键字: AI 嵌入式 相机

为增进大家对嵌入式主板的认识,本文将对嵌入式主板以及嵌入式主板常见问题及其解决方法予以介绍。

关键字: 嵌入式 指数 主板

为增进大家对嵌入式系统的认识,本文将对嵌入式系统、嵌入式系统的特点予以介绍。

关键字: 嵌入式 指数 嵌入式系统

为增进大家对嵌入式的认识,本文将对嵌入式、嵌入式工作相关的内容予以介绍。

关键字: 嵌入式 指数 嵌入式技术

机器人操作系统(ROS)驱动程序基于ADI产品而开发,因此可直接在ROS生态系统中使用这些产品。本文将概述如何在应用、产品和系统(例如,自主导航、安全气泡地图和数据收集机器人)中使用和集成这些驱动程序;以及这样将如何有助...

关键字: 电机控制器 机器人 嵌入式

支持高达48V@5A的PD受电模式,达到目前USB PD最高标准。

关键字: 嵌入式 开发板

载波抑制这一术语在通信技术和电力电子学领域具有不同的含义,本篇文章将分别从这两个角度展开讨论,阐述载波抑制的概念、工作原理以及应用场景。

关键字: 载波抑制 通信技术

【2024年4月8日,德国慕尼黑讯】低碳化和数字化是当今时代人们面临的两大核心挑战,人类社会需要依靠创新和先进的技术,才能破除挑战、推动转型进程。在德国纽伦堡举办的2024国际嵌入式展(Embedded World 20...

关键字: 半导体 微控制器 嵌入式
关闭
关闭