嵌入式开发一直都存在“效率低下”的问题,很多人疑惑,也搞不明白到底咋回事?
不矫情,我们直接上mqtt的源代码。
1、假设已经顺利解决了mqtt的源代码在Linux上的编译问题(经验表明该过程从来都不顺利,按下不表),下面开始mqtt协议的使用;
2、首先,寻找到一个demo工程,看看作者想要我们怎么操作,如下图:
从代码中可粗看,例子中先建立一个context,然后调用connect,等待一会再调用disconnect函数,没有多余流程,大概了解只是介绍了如何连接平台。
竟然这么简单,简直捡到宝了!!!是这样吗???
3、调用MQTTAsync_create,但是不知道它的各个形参都什么意思?什么格式?怎么使用?注意什么?继续寻找函数解释,如下图:
从这大段英文解释中,知道了需要传递一个指针地址,网站地址,clientid,持久化类型,持久化上下文,这里网站地址格式具体是啥?持久化类型和上下文是啥?怎么用?需要研究mqtt官方协议文档才能明白,文档就不贴了。里面有提到了persistence函数和destroy函数,跟这俩什么关系?都得查资料。
里面的MQTTAsync是什么鬼?看代码吧
差点一屏没截完,里面好多注释是我加的,结合代码分析,大概了解了这是一个保存某个连接参数和状态等等一些列信息的最外层索引结构,系统分配保存,只给我们一个指针用,具体单个变量含义就不说了,具体每个函数时都会涉及到这些变量的操作。
4、知道了这些参数的含义是不是就可以上手了,没那么简单,这些指针表示的数据,我是malloc一直给系统用,还是用局部变量调用完就释放,这直接决定了会不会内存泄漏,也没人跟我说,需要翻看这个函数里面到底是怎么操作我给的数据的。进入函数:
不好,有一个子函数,那就得分析为啥搞个子函数?发现这个子函数也提供给了用户使用,那这俩有啥区别?又得从子函数的参数意义入手了。搜索发现该子函数没有任何注释,而且上一个问题也没有解决,那就只能硬着头皮继续了。
5、进入MQTTAsync_createWithOptins里面,看看它到底是怎么使用我给的数据的?这决定了我该不该保留数据,以什么形式保留数据?带着疑问进入函数:
进入后发现函数超大,这里只标注了一部分数据。
为解决疑问1(怎么处理我给的数据的),需要依次对该函数的每个参数过一遍,看系统是怎么处理的,它有没有保存下来我给的参数,发现MQTTStrdump函数处理我给的数据,继续进入内部发现它重新申请了内存,保存了我的clientid,那明白了我给的参数就可以用完释放了,不占用系统空间。
(注意:对mqtt库来说允许释放,但到底需不需要保存,需要根据我如何设计自动重连功能,进一步考虑数据存放的形式,最终来决定这里只考虑mqtt函数限制),同样方法查找其他参数。
对问题2,connect和connectWIthOption到底差异到哪儿?看最后一个参数的差别,发现在持久化上,那继续翻看MQTT官方协议看持久化章节的规定,看MQTTPersistence_create函数内部到底怎么处理的持久化,我需不需要对该数据进行保存等等。
最后还需要做决定,对mqtt库提供的这俩函数,到底选择哪一个,哪个更适合我们的业务。继续翻看代码……,终于在崩溃前,我决定用connect函数。
6、对这个connect函数里外翻了一遍后,我们就开始涉及自己的数据结构,哪些是需要直接确定隐藏不给用户看的,哪些是需要用户传递的,这就涉及到产品需求和业务逻辑了,需要花时间分析,这里省略;
7、解决了第一个函数,是不是只有第一个函数复杂,其他都是so easy
那再看第二个:
对这个函数,大概意思是注册callback函数的,那都有哪些callback函数?挨个查他们的定义,好确定如何操作(过程就省略,不贴图了)。
知道了定义,就可以直接用了?不是的,需要确定这些函数指针是不是可以传NULL,原则上我传NULL,告诉系统我不想接收回调数据没毛病啊,细看发现允许cl和dc为NULL,不允许ma为空,这都需要我们一行行分析代码。
再分析发现,我们必须传递消息到来的接收函数否则系统就不认,天哪,除了看代码竟然没人告诉我,需要这样操作。
退一步,如果一开始不看这些代码直接给了NULL,恰好又向demo里那样没判断返回值(这很常见,看第一张图),那就等着以后调试时,问题频出焦头烂额吧,等着测试小姐姐一个一个的bug上报,心跳加速吧。
8、剩下的其他一大推什么订阅,发布,接收等等函数就不分析了,就这一个create函数,保证你1天都搞不明白,上面都省略了函数查找的过程,省略了分析执行逻辑的过程,省略了挨个字节分析mqtt协议的过程,省略了专业英文翻译的过程。
说了一大推,发现只搞明白了一个最简单create 的函数的使用,还有连接,注册,发布接收这些哪个都都比create复杂的多。
不就调用一个函数吗?总共写下来就一行,不超过50个字母,怎么那么磨叽,还一步都不能省,我要求不高,只是想好好的调用一个函数而已,这么费劲招谁惹谁了?
咳咳,这还是在linux平台上,还没考虑每个芯片的特性,芯片的寄存器设置规则,芯片的技术手册描述,电路图的设计约束,没考虑操作系统的限制,没考虑……
说了这么多,你是不是能稍微理解嵌入式开发的“低效率”了,以后把“低效率”换成是“负责任”,或许会让大家更舒服些!