嵌入式開發一直都存在“效率低下”的問題,很多人疑惑,也搞不明白到底咋回事?
不矯情,我們直接上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平臺上,還沒考慮每個芯片的特性,芯片的寄存器設置規則,芯片的技術手冊描述,電路圖的設計約束,沒考慮操作系統的限制,沒考慮……
說了這么多,你是不是能稍微理解嵌入式開發的“低效率”了,以后把“低效率”換成是“負責任”,或許會讓大家更舒服些!