梁雪濤 李升建 張延良 薛雷 宋業(yè)棟

摘 要:本文詳細(xì)介紹了一種系統(tǒng)編纂設(shè)備日志的方法。通過面向間隙的思想,優(yōu)化軟件結(jié)構(gòu),簡便有效的創(chuàng)建一種基于C語言的日志系統(tǒng)。以實(shí)現(xiàn)軟件狀態(tài)的監(jiān)測,切實(shí)有效的提高故障排查效率,為軟件開發(fā)和維護(hù)提供一種高效的開發(fā)方案。
關(guān)鍵詞:面向間隙;單片機(jī);編程思維及方法
中圖分類號:TP311.52 文獻(xiàn)標(biāo)識碼:A 文章編號:1671-2064(2020)13-0047-02
0引言
近年來,隨著物聯(lián)網(wǎng)產(chǎn)業(yè)的發(fā)展和相關(guān)政策的落地,市場對于簡單可靠的單片機(jī)數(shù)采設(shè)備需求量越來越高。而目前對于這種小型硬件,Linux系統(tǒng)占據(jù)著無可置疑的統(tǒng)治地位。但是對于更小的硬件,以成本經(jīng)濟(jì)性考慮并未植入Linux系統(tǒng)。在缺少成型操作系統(tǒng)支持的情況下,日志、任務(wù)調(diào)度等重要功能的缺失使得簡單單片機(jī)程序設(shè)計(jì)思想已無法滿足日益增長的功能需求。而在開發(fā)過程中,日志系統(tǒng)在排查bug和程序檢測方面均具有重要意義。本文立足于樸素單片機(jī)環(huán)境,提出一種簡單有效的日志系統(tǒng)建立方法和編程思想,為此細(xì)分領(lǐng)域的程序開發(fā)提供一種切實(shí)有效的開發(fā)方案。
1面向間隙的基本理念
眾所周知,目前的大多數(shù)程序,其結(jié)構(gòu)大抵按照OSI七層模型構(gòu)建[1],如圖1所示。
按照此模型,各代碼層之間通過接口交互,實(shí)現(xiàn)彼此間的數(shù)據(jù)交換和功能實(shí)現(xiàn)。如應(yīng)用層僅會調(diào)用底層的功能接口,并由程序員手動對接口的返回結(jié)果進(jìn)行校驗(yàn)[2]。在此過程中的一切處理皆因調(diào)用位置不同而異,調(diào)用十次即需重寫十次校驗(yàn)結(jié)果和校驗(yàn)后的處理代碼。一方面難以生成系統(tǒng)的日志和錯誤警報(bào),另一方面極易缺失結(jié)果校驗(yàn),造成后期bug排查困難,耗時長,效率低。
在JavaSpringBoot[3]中,存在人為構(gòu)建切面作為日志監(jiān)控點(diǎn)的思想。而面向間隙的思想與其類似,只是監(jiān)控點(diǎn)無需人為特意搭建,而是直接監(jiān)控接口。在各代碼層發(fā)生交互的間隙內(nèi)組織監(jiān)控代碼,實(shí)現(xiàn)對接口調(diào)用的實(shí)時監(jiān)控,并自主生成相應(yīng)日志,完成對接口反饋的校驗(yàn)和錯誤報(bào)警,最終實(shí)現(xiàn)對軟件運(yùn)行狀況的實(shí)時監(jiān)控。
2間隙層的結(jié)構(gòu)
對于間隙層,其主體結(jié)構(gòu)可分為兩個部分:包裝層、引用層。
2.1包裝層
包裝層主要負(fù)責(zé)對結(jié)構(gòu)進(jìn)行額外包裝,包裝內(nèi)容包括接口反饋校驗(yàn)、日志主體代碼及其他額外內(nèi)容。
2.1.1接口反饋校驗(yàn)
此部分即為對接口返回值的第一次校驗(yàn),如接口反饋失敗,應(yīng)向日志內(nèi)寫入報(bào)錯相關(guān)信息。反饋成功則應(yīng)視其重要性生成相關(guān)日志信息。
2.1.2日志主體代碼
此部分負(fù)責(zé)記錄接口引用位置、引用時間、引用者、接口反饋結(jié)果等日志基本信息。
2.1.3其他額外內(nèi)容
此部分可提供空函數(shù)指針,用于后期視需求拓展其他代碼,如回調(diào)函數(shù)。
2.1.4包裝層的具體示例
下面以GenSend接口為例:
此接口的具體信息如下:
名稱:bool GenSend(u8* Dat,u16 Datlen)
功能:發(fā)送數(shù)據(jù)
輸入: Dat發(fā)送數(shù)據(jù)的地址
Datlen發(fā)送數(shù)據(jù)的長度
返回: ture發(fā)送成功
false發(fā)送失敗
此接口可被包裝為一個新接口GenSendPacked
新接口的具體信息如下:
名稱:bool GenSendPacked(u8* Dat,u16 Datlen,u8 Sign)
功能:發(fā)送數(shù)據(jù),生成相關(guān)日志
輸入: Dat發(fā)送數(shù)據(jù)的地址
Datlen發(fā)送數(shù)據(jù)的長度
Sign調(diào)用標(biāo)志符
返回: true調(diào)用成功
false調(diào)用失敗
具體代碼如下:
bool GenSendPacked(u8* Dat,u16 Datlen,u8
Sign,void(*fp)(void))
{
//日志主體部分
LogWrInfor(GENSEND,Sign);
//可擴(kuò)展函數(shù)
fp();
if(GenSend(Dat,Datlen))
{//返回值校驗(yàn)
LogWrError(GENSEND);
return false;
}
else return true;
}
在GenSendPack接口中,日志主體部分LogWrInfor函數(shù)引用了GENSEND宏和Sign變量來描述此接口的引用狀況。GENSEND宏用于描述接口ID,以在日志中說明是哪一個接口被引用。Sign變量則用于描述引用位置,在日志中描述其在程序的哪個位置被引用。
fp()為空置的函數(shù)指針,用于之后的擴(kuò)展內(nèi)容。
LogWrError的功能為向日志中寫入錯誤信息,使用其引用的接口ID宏(此例中即為GENSEND)描述錯誤狀態(tài)。
如上包裝后,每次底層接口被引用時則會在日志中寫入引用記錄和可能存在的報(bào)錯信息。但包裝層無法解決另一問題:每次對接口的引用都必須校驗(yàn)結(jié)果。為了解決此問題,本文引入了面向間隙的第二個主要部分——引用層。
2.2 引用層
引用層主要負(fù)責(zé)對接口進(jìn)行宏包裝,使得后續(xù)編程引用此接口時無需再進(jìn)行繁瑣的校驗(yàn)過程。
所謂宏包裝,是指利用宏可定義變量的句法特點(diǎn),將接口與其校驗(yàn)過程定義為宏。
依舊以GenSend接口為例,對此接口包裝如下:
#define D_GenSendPacked(a,b,c,d)? if(GenSend-Packed(a,b,c,d)) return;
在添加了引用層之后,僅需使用D_ GenSendPacked
()宏即可直接調(diào)用GenSend接口,無需進(jìn)行其他多余操作。
3日志系統(tǒng)基本結(jié)構(gòu)
使用面向間隙思維所創(chuàng)建的日志系統(tǒng),其基本思想為使用接口ID和引用者ID來描述引用者、被引用者,并使用LogError函數(shù)來描述引用結(jié)果。同時如需必要,亦可記錄接口中流通的數(shù)據(jù)體詳細(xì)信息。
日志系統(tǒng)的基本結(jié)構(gòu)可分為以下幾部分:
3.1數(shù)據(jù)輸入部分
面向間隙的相關(guān)監(jiān)控代碼塊。此部分負(fù)責(zé)輸入被引用接口的接口ID、引用者ID、接口中流通的數(shù)據(jù)及其他需要記錄入日志的信息。
3.2存儲部分
此部分可靈活使用Flash、EMCC、SD卡等物理載體,文件、Flash扇區(qū)存儲方法進(jìn)行存儲,且應(yīng)在存儲滿后覆蓋起始部分。
3.3輸出部分
此部分可視具體需求實(shí)現(xiàn)實(shí)時輸出、按條件導(dǎo)出等輸出模式。
4架構(gòu)設(shè)計(jì)及后期移植
在七層模型中插入間隙層后,日志系統(tǒng)和接口校驗(yàn)就不再是一個需要在代碼架構(gòu)設(shè)計(jì)階段需要訴諸精力的部分。且間隙層在后續(xù)的平臺移植過程中,天然具有的低耦合性相比其他插入式日志系統(tǒng)具有較大優(yōu)勢。
5結(jié)語
在樸素單片機(jī)系統(tǒng)這一領(lǐng)域內(nèi),經(jīng)濟(jì)性和維護(hù)簡易度被高度重視,因此日志系統(tǒng)的開發(fā)無疑具有重要的意義。目前的日志系統(tǒng),搭建過程能夠借鑒的編程模板極多且具有大量的成型框架,比如[4]Java的SpringBoot、Linux自帶的成型日志系統(tǒng)或[5]其他基于串口、[6]AETA的日志系統(tǒng)。但對于樸素單片機(jī)終端而言,高級語言的系統(tǒng)移植難度極大,而Linux的內(nèi)核裁剪則相對復(fù)雜繁瑣,且對相關(guān)工程師的能力要求較高,較高的人力成本也拉高了產(chǎn)品成本。這種背景下,一種簡單有效、易于維護(hù)的日志系統(tǒng)亟需被開發(fā)出來用于樸素單片機(jī)遠(yuǎn)程終端市場。而如本文所述,面向間隙的相關(guān)代碼塊與接口是一種并生關(guān)系。接口被引用時相關(guān)監(jiān)控代碼就會被觸發(fā)。基于此,基本思想構(gòu)建出的日志系統(tǒng)結(jié)構(gòu)簡單,本身與上層應(yīng)用軟件伴生,支持靈活的擴(kuò)展及后期維護(hù)。[7]而實(shí)際上在軟件中,函數(shù)和函數(shù)間亦可以認(rèn)為是一個個相互隔離的面,函數(shù)間同樣存在間隙。因此,面向間隙也可以和函數(shù)綁定,實(shí)現(xiàn)關(guān)鍵函數(shù)的數(shù)據(jù)孿生。以此搭建的程序在開發(fā)和維護(hù)尚對比傳統(tǒng)程序均存在效率和成本優(yōu)勢,可以為物聯(lián)網(wǎng)系統(tǒng)開發(fā)、高數(shù)據(jù)量應(yīng)用(如VR、AR、智能駕駛、城際智能資源調(diào)度等)的底層搭建提供廣闊的前景,并能為大規(guī)模鋪設(shè)基礎(chǔ)智能終端減少大量成本,推動物聯(lián)網(wǎng)領(lǐng)域盡快走進(jìn)智能網(wǎng)聯(lián)時代。
參考文獻(xiàn)
[1] 涂小琴.C語言結(jié)構(gòu)化編程教學(xué)案例過程設(shè)計(jì)[J].現(xiàn)代計(jì)算機(jī)(專業(yè)版),2017(30):72-76.
[2] 叢剛.微型機(jī)BASIC語言結(jié)構(gòu)化編程方法探討[J].成都電訊工程學(xué)院學(xué)報(bào),1988(s2):191-192.
[3] 宋佳,范偉,黃鵬.基于Spring的Java平臺程序架構(gòu)研究[J].計(jì)算機(jī)與網(wǎng)絡(luò),2016,42(22):68-71.
[4] 王童童.面向切面的軟件容錯技術(shù)研究[D].西安:西安電子科技大學(xué),2015.
[5] 李亞洲.基于串口通信的單片機(jī)日志系統(tǒng)設(shè)計(jì)[J].工業(yè)控制計(jì)算機(jī),2009,22(11):44-45.
[6] 周康生,張興,王新安,等.一種適用于AETA的日志系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)技術(shù)與發(fā)展,2019,29(12):8-13.
[7] 王興念,吳六一,李立生,等.基于面向切面編程的跨區(qū)傳輸跟蹤與測試技術(shù)應(yīng)用[C].中國電力科學(xué)研究院有限公司、國網(wǎng)電投(北京)科技中心、《電信科學(xué)》雜志社.第三屆智能電網(wǎng)會議論文集.中國電力科學(xué)研究院有限公司、國網(wǎng)電投(北京)科技中心、《電信科學(xué)》雜志社:國網(wǎng)電投(北京)科技中心,2018:118-124.
Abstract:This paper introduces a method of compiling equipment log system in detail. Through the idea of Facing-gap, the software structure is optimized, and a log system based on C language is created simply and effectively to realize the detection of software status, effectively improve the efficiency of troubleshooting, and provide an efficient development scheme for software development and maintenance.
Key words:facing-gap;singlechip;programming thinking and methods
收稿日期:2020-06-03
作者簡介:梁雪濤(1996—),男,山東青島人,本科,軟件工程師,研究方向:網(wǎng)聯(lián)終端開發(fā)。