許璟鋒
摘要:在嵌入式系統(tǒng)開(kāi)發(fā)中,用戶都希望能有一個(gè)日志文件能監(jiān)控、記錄系統(tǒng)的運(yùn)行狀況,在出現(xiàn)問(wèn)題時(shí)能在日志文件中記錄下相應(yīng)的信息。該文提供了一種可行的日志文件的開(kāi)發(fā)方法。在文章中,筆者提供了日志文件的總體開(kāi)發(fā)思想、相應(yīng)的數(shù)據(jù)結(jié)構(gòu),并指出的開(kāi)發(fā)過(guò)程中一些需要注意的問(wèn)題。
關(guān)鍵詞:嵌入式系統(tǒng);日志;數(shù)據(jù)結(jié)構(gòu)
中圖分類號(hào):TP311 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1009-3044(2014)21-5687-02
An Implementation of Real-Time Event Logging
XU Jing-feng
(Department of Basic Research, Nanjing Institute of Politics, Nanjing 210003, China)
Abstract: In the process of developing an embedded system,the users want a log to monitor ,record the system and find out the errors when the system corrupt.The paper provides the readers with the general developing methods,data structure and the operation in the background.
Key words: Embedded System; log; Data Structure
在嵌入式系統(tǒng)中,日志文件既可以用來(lái)監(jiān)視設(shè)備運(yùn)行狀況,也可以用來(lái)進(jìn)行查找錯(cuò)誤。很多情況下,我們無(wú)法判斷是什么造成系統(tǒng)出了問(wèn)題,更無(wú)法準(zhǔn)確說(shuō)出是什么時(shí)間出了問(wèn)題。因?yàn)楹芏鄦?wèn)題如引腳彎曲所造成的情況往往是間歇性的甚至根本無(wú)法再重復(fù)出現(xiàn)的,如果有了日志文件,用戶就可以通過(guò)它的成功/失敗率來(lái)確定情況,同時(shí)也有一份將所有的問(wèn)題都詳細(xì)記錄下來(lái)的報(bào)告,對(duì)于那些很難隔離的錯(cuò)誤也可以詳細(xì)的記錄下來(lái)方便識(shí)別。但由于各種原因,它的開(kāi)發(fā)和應(yīng)用并不普及。本文介紹了怎樣在一個(gè)嵌入式系統(tǒng)中開(kāi)發(fā)成本較低的日志文件系統(tǒng)。
1 硬件要求
對(duì)于一個(gè)由中央微處理器控制的設(shè)備來(lái)說(shuō),添加了日志文件就可以在半導(dǎo)體內(nèi)存記錄中保存時(shí)間、日期和關(guān)鍵事件的運(yùn)行結(jié)果。通過(guò)它,用戶就能將特定事件記錄下來(lái),以便于監(jiān)控、改進(jìn)今后的設(shè)備運(yùn)行。本方法的硬件成本很低,只需要增加一個(gè)用來(lái)保存日志文件的EEPROM和一個(gè)實(shí)時(shí)時(shí)鐘。由于這很容易實(shí)現(xiàn),本文不做介紹。
2 軟件實(shí)現(xiàn)
我們的方法是將日志信息記錄在日志文件中,在EEPROM中保存。一旦一個(gè)事件被記錄下來(lái)后,相應(yīng)事件的代碼就會(huì)調(diào)用日志事件函數(shù),這個(gè)函數(shù)會(huì)與實(shí)時(shí)時(shí)鐘的信息一起將相應(yīng)的信息存儲(chǔ)到EEPROM中。由于EEPROM的空間有限,當(dāng)空間滿了后,最老的數(shù)據(jù)會(huì)被最新的數(shù)據(jù)代替。
對(duì)于日志記錄,我們將它們劃分為4個(gè)級(jí)別,分別是無(wú)、低級(jí)、中級(jí)、高級(jí)。日志文件可以在同一時(shí)間保存不同級(jí)別的日志信息。日志信息的級(jí)別越高,在EEPROM中所占空間越大,保留的記錄條數(shù)就越少,同時(shí)也要花更多的時(shí)間來(lái)寫入。
設(shè)置不同的日志級(jí)別是為了方便用戶對(duì)任一事件改變記錄的數(shù)目。例如,在使用設(shè)備過(guò)程中,通常其級(jí)別是處于低級(jí)的狀態(tài),這時(shí)用戶可以得一些諸如設(shè)備何時(shí)啟動(dòng)、何時(shí)關(guān)閉、總體成功/失敗率等較為概略性的信息。而當(dāng)用戶希望監(jiān)控某一特定socket的成功/失敗率信息時(shí),就需將級(jí)別提升為中級(jí)了。而當(dāng)一個(gè)錯(cuò)誤反復(fù)出現(xiàn)卻很難確定時(shí),可將級(jí)別調(diào)整至高級(jí),這時(shí)日志文件會(huì)將相應(yīng)socket的信息、有關(guān)的地址和數(shù)據(jù)都記錄下來(lái)。
下面列出的是對(duì)同一事件的不同記錄級(jí)別的信息進(jìn)行記錄的代碼:
/* 將日志數(shù)據(jù)從EEPROM復(fù)制到RAM中進(jìn)行更新*/
uint get_log(Log_File_*log_ptr, ushort log_rec_num){
Log_File *find_ptr;
if ((find_ptr =find_log_rec(log_rec_num)) == NULL) return FAIL;
memcpy(log_ptr,find_ptr,find_ptr-<;>log_low.rec_len);
return PASS;
}
一旦一個(gè)事件發(fā)生,它會(huì)被記錄到相應(yīng)級(jí)別的數(shù)據(jù)末尾。由于事件發(fā)生所花費(fèi)的時(shí)間通常是在整個(gè)事件發(fā)生后才結(jié)束,所以這不會(huì)降低相系統(tǒng)對(duì)相應(yīng)事件的反應(yīng)時(shí)間。
3 日志文件的數(shù)據(jù)結(jié)構(gòu)
日志文件的數(shù)據(jù)結(jié)構(gòu)可根據(jù)自己系統(tǒng)的具體情況來(lái)決定,這里列出我們系統(tǒng)的數(shù)據(jù)結(jié)構(gòu):
typedef struct { /* 低級(jí)事件的日志記錄數(shù)據(jù)結(jié)構(gòu) */
ushort rec_num;
uchar event_num;
uchar level;
uchar version;
uchar rec_len;
; /* 設(shè)備專用的數(shù)據(jù)塊 */
uchar rec_chksum_med;
uchar rec_chksum_high;
uchar rec_chksum_low;
} Log_Base;
typedef struct{ /* 中級(jí)事件的數(shù)據(jù)結(jié)構(gòu) */
; /* 設(shè)備專用的數(shù)據(jù)塊 */
} Log_Med_Detail;
typedef struct{ /* 高級(jí)事件的數(shù)據(jù)結(jié)構(gòu) */
; /* 設(shè)備的專用數(shù)據(jù)塊 */
} Log_High_Detail;
typedef struct { /* 日志文件的記錄定義 */
Log_Base log_low;
Log_Med_Detail log_med;
Log_High_Detail log_high;
} Log_File;
我們列出高級(jí)事件的記錄,讀讀者可根據(jù)下面的數(shù)據(jù)得出相應(yīng)的數(shù)據(jù)結(jié)構(gòu)來(lái):
Low PV:VERIFY P:5 F:2
TP:5 TF:2 IMI#:003C
SS:1 DW:8 CRC:FOB8
MOD:3 AD:1
Passed Socket(s): 1 3 5 6 7
Failed Socket: 2 Err:Verify
Adx:0 Dev:00 RAM:FF
Failed Socket: 4 Err:Verify
Adx:12 Dev:FA RAM:FF\&]
需要注意的是日志文件的記錄還應(yīng)包含一個(gè)校驗(yàn)字節(jié)和一個(gè)狀態(tài)字節(jié),這樣就可以檢查并標(biāo)記出受損的記錄。另外日志文件的不同級(jí)別都被設(shè)置成了相應(yīng)的固定大小的塊,這樣在檢查日志文件錯(cuò)誤或恢復(fù)受損數(shù)據(jù)時(shí)比采用動(dòng)態(tài)大小的塊要容易些。
最后用戶還需要通過(guò)鍵盤或終端做如下工作:清理日志文件或刪除損壞的記錄、將日志文件導(dǎo)入計(jì)算機(jī)、抹掉整個(gè)日志文件、讀日志文件記錄、選擇所需的日志事件、放棄選擇所需的日志事件、設(shè)置日志文件層次等等。
參考文獻(xiàn):
[1] 彭蔓蔓,李浪,徐署華.嵌入式系統(tǒng)導(dǎo)論[M].北京:人民郵電出版社,2008.
[2] 懷特.嵌入式系統(tǒng)設(shè)計(jì)與實(shí)踐[M].余水清,譯.北京:機(jī)械工業(yè)出版社,2013.