文獻(xiàn)標(biāo)識(shí)碼: A
文章編號(hào): 0258-7998(2015)03-0024-04
0 引言
盡管Linux作為嵌入式操作系統(tǒng)有著諸多的優(yōu)勢(shì),,但是由于嵌入式操作系統(tǒng)自身的特點(diǎn),如嵌入式應(yīng)用范圍的多樣性和復(fù)雜性,,導(dǎo)致嵌入式產(chǎn)品維護(hù)難度大的問(wèn)題更加突出,。嵌入式系統(tǒng)在實(shí)際環(huán)境中投入運(yùn)行后,掉電等意外的災(zāi)難,、用戶錯(cuò)誤或惡意地對(duì)數(shù)據(jù)進(jìn)行修改和刪除,、一部分無(wú)法在開(kāi)發(fā)中充分測(cè)試的錯(cuò)誤等都會(huì)導(dǎo)致功能失效,嚴(yán)重的可能導(dǎo)致系統(tǒng)癱瘓,。如果采用人工更新方式,,由于安裝位置等因素有時(shí)會(huì)不方便。因此,,嵌入式系統(tǒng)的自動(dòng)備份與恢復(fù)機(jī)制是恢復(fù)數(shù)據(jù)最容易和最有效的保證方法[1],,并逐漸成為嵌入式系統(tǒng)實(shí)際應(yīng)用中的一個(gè)重要問(wèn)題。
目前,,普遍使用雙機(jī)熱備份[2],、容災(zāi)備份[3]等技術(shù)做為實(shí)現(xiàn)嵌入式系統(tǒng)高可靠性的設(shè)計(jì)方案,由于采用獨(dú)立的兩套系統(tǒng),,因此增加了一定的設(shè)計(jì)難度和成本[4],。本文針對(duì)當(dāng)前嵌入式系統(tǒng)備份技術(shù)存在的一些問(wèn)題,通過(guò)分析嵌入式U-Boot及Linux內(nèi)核,,將嵌入式系統(tǒng)鏡像在一套設(shè)備上備份為多份,,每次僅有一個(gè)系統(tǒng)運(yùn)行。當(dāng)運(yùn)行的操作系統(tǒng)出現(xiàn)故障時(shí),,就會(huì)觸發(fā)系統(tǒng)備份恢復(fù)機(jī)制,,使用下一個(gè)可用的備份分區(qū)覆蓋掉出現(xiàn)故障的系統(tǒng)分區(qū),然后啟動(dòng)下一個(gè)可用的系統(tǒng),。整個(gè)系統(tǒng)不需要備用設(shè)備,,大大地節(jié)約了成本和功耗,,提高了系統(tǒng)的穩(wěn)定性和可靠性。
1 系統(tǒng)總體方案設(shè)計(jì)
1.1 系統(tǒng)總體設(shè)計(jì)
嵌入式Linux系統(tǒng)中的備份與恢復(fù)總體實(shí)現(xiàn)方案如圖1所示,。
該系統(tǒng)由x-loader(SPL),、U-Boot、U-Boot Env,、Judge-
Area,、Kernel(uImage)和Rootfs(ubi.img)六部分組成。mtd是同一NAND Flash上劃分出的不同分區(qū),,并且uImage和ubi.img在設(shè)備上備份了多份,系統(tǒng)各組成部分特性及作用介紹如下:
(1)x-loader是一級(jí)引導(dǎo)程序[5],,U-Boot是二級(jí)引導(dǎo)程序[6],,U-Boot Env存儲(chǔ)內(nèi)核啟動(dòng)參數(shù)。
(2)Judge-Area存儲(chǔ)系統(tǒng)備份及恢復(fù)參數(shù),。在U-Boot和Linux下可以共享訪問(wèn),。
(3)Kernel是Linux內(nèi)核[7],Rootfs采用開(kāi)源的無(wú)排序區(qū)塊圖像文件系統(tǒng)UBIFS(Unsorted Block Image File System),,特別適用于嵌入式系統(tǒng)[8],。
A、B,、C均為系統(tǒng)鏡像區(qū),,存放內(nèi)核和文件系統(tǒng)。U-Boot通過(guò)判斷Judge-Area中的參數(shù),,啟動(dòng)其中一個(gè)系統(tǒng)鏡像區(qū),,并將啟動(dòng)過(guò)程中的故障情況反饋給Judge-Area。當(dāng)系統(tǒng)運(yùn)行出現(xiàn)故障或者崩潰時(shí),,使用watchdog機(jī)制來(lái)使其硬件復(fù)位,,通過(guò)U-Boot下的自動(dòng)備份恢復(fù)機(jī)制,用其他可運(yùn)行的備份來(lái)覆蓋出現(xiàn)故障的系統(tǒng)鏡像區(qū),,確保能啟動(dòng)一個(gè)可用系統(tǒng),。
目前運(yùn)行Linux系統(tǒng)的NAND Flash配置都比較大,而裁剪后的內(nèi)核和精簡(jiǎn)的UBI文件系統(tǒng)實(shí)際占用不到20 MB容量,,或者更少[9],。因此,這為實(shí)現(xiàn)Linux系統(tǒng)的多重備份提供了可能,。
1.2 備份及恢復(fù)機(jī)制
下面以三重備份與恢復(fù)為例來(lái)說(shuō)明系統(tǒng)的備份及恢復(fù)流程,,整個(gè)系統(tǒng)鏡像分3個(gè)地方保存在NAND Flash,具體的過(guò)程如下:
(1)系統(tǒng)上電或復(fù)位U-Boot啟動(dòng)運(yùn)行,,假設(shè)A區(qū)相關(guān)的r_active_1(引導(dǎo)標(biāo)志)和b_success_1(內(nèi)核啟動(dòng)成功標(biāo)志)為“yes”,,BC區(qū)域均為“no”,。在系統(tǒng)鏡像未成功啟動(dòng)以前的過(guò)程可以認(rèn)為是啟動(dòng)失敗的,所以先設(shè)置A區(qū)r_active_1,、b_success_1為“no”,,rec_kernel_1(內(nèi)核恢復(fù)標(biāo)志)、rec_fs_1(文件系統(tǒng)恢復(fù)標(biāo)志)為“yes”,。還要設(shè)置B區(qū)r_active_2,、b_success_2為“yes”。
(2)然后U-Boot加載A區(qū)域的系統(tǒng),,若Linux系統(tǒng)運(yùn)行正常,,則在Linux下還原所有標(biāo)志值為初始值。若引導(dǎo)失敗,,則若干時(shí)間后觸發(fā)watchdog復(fù)位系統(tǒng),,此時(shí)U-Boot再次運(yùn)行,判斷b_success_1為“no”,,表示上次引導(dǎo)失敗,,并且rec_kernel_1、rec_fs_1為“yes”,,表示需要將B區(qū)的內(nèi)核及文件系統(tǒng)覆蓋到A區(qū),,覆蓋成功后清除恢復(fù)標(biāo)志和重置b_success_1,再通過(guò)watchdog復(fù)位系統(tǒng),。
(3)U-Boot判斷r_active_2,、b_success_2為“yes”,故選擇啟動(dòng)B區(qū)域的系統(tǒng),。在系統(tǒng)啟動(dòng)成功以前,,設(shè)置B區(qū)r_active_2、b_success_2為“no”,,rec_kernel_2,、rec_fs_2為“yes”,還要設(shè)置C區(qū)r_active_3為“yes”,。
(4)加載B區(qū)域的系統(tǒng),,若Linux系統(tǒng)能正常運(yùn)行,則在Linux下還原所有標(biāo)志為初始值,。如果B區(qū)也失敗了,,復(fù)位系統(tǒng),在U-Boot下用C區(qū)覆蓋B區(qū)域,。覆蓋成功后清除恢復(fù)標(biāo)志和重置b_success_2,,再通過(guò)watchdog復(fù)位系統(tǒng)。同理,,再?gòu)腃區(qū)域的系統(tǒng)啟動(dòng),,當(dāng)C區(qū)域也出現(xiàn)問(wèn)題后,,則重新從A區(qū)域啟動(dòng),循環(huán)依次選擇,。
2 系統(tǒng)實(shí)現(xiàn)
2.1 Judge-Area基礎(chǔ)設(shè)計(jì)
Judge-Area是在NAND Flash上劃分出的單獨(dú)區(qū)域,,內(nèi)部存儲(chǔ)系統(tǒng)備份及恢復(fù)的環(huán)境參數(shù),該區(qū)類似U-Boot Env區(qū)域,。
為了能在U-Boot下查看和修改這些參數(shù),,將本區(qū)域的所有參數(shù)定義在一個(gè)judge_tab數(shù)組中,然后導(dǎo)入到哈希表judge_htab中,。
struct hsearch_data judge_htab;
himport_r(&judge_htab, (char *)judge_tab, \
sizeof(judge_tab), ′\0′, 0)
為方便調(diào)試和實(shí)現(xiàn)手動(dòng)進(jìn)行備份恢復(fù)操作,,添加U-Boot下串口打印命令printjudge,修改命令setjudge,,保存命令savejudge,。打印命令printjudge的實(shí)現(xiàn)為:
/* print a single name */
hsearch_r(e, FIND, &ep, &judge_htab);
/* print whole list */
len=hexport_r(&judge_htab, ′\n′, &res, 0),;
同理,修改命令setjudge也是對(duì)judge_htab的簡(jiǎn)單操作,,由于這些修改只是對(duì)內(nèi)存上的數(shù)值進(jìn)行操作,,所以修改后的值沒(méi)有保存在NAND Flash中。保存命令savejudge便是對(duì)這些變量進(jìn)行存儲(chǔ),,存儲(chǔ)的過(guò)程如下:使用hexport_r將數(shù)據(jù)導(dǎo)出到新的哈希表judge_htab_new,,然后調(diào)用nand_erase_opts擦除Judge-Area區(qū)域,最后使用nand_write將數(shù)據(jù)寫入到該區(qū)域,。為提高讀寫數(shù)據(jù)的可靠性,,開(kāi)啟硬件壞塊檢測(cè)、ECC校驗(yàn),。
2.2 U-Boot下備份及恢復(fù)設(shè)計(jì)
U-Boot下備份及恢復(fù)機(jī)制設(shè)計(jì)如圖2所示,。
函數(shù)judge_get()實(shí)際上調(diào)用hsearch_r函數(shù)查詢哈希表judge_htab,從Judge-Area讀取下一個(gè)系統(tǒng)鏡像的地址addr_x及大小size_x,。
函數(shù)img_recover()的功能是調(diào)用img_read,、img_write恢復(fù)下一個(gè)系統(tǒng)鏡像到當(dāng)前系統(tǒng)鏡像區(qū)。
Judge-Area參數(shù)重置函數(shù)judge_reset()主要工作是調(diào)用setjudge分別設(shè)置b_success_x為"yes",,設(shè)置rec_fs_x,、rec_kernel_x為"no"。
U-Boot Env參數(shù)重置函數(shù)uEnv_reset()的工作是調(diào)用setenv設(shè)置nand_src_addr,、nand_img_siz,、nand_root對(duì)應(yīng)為"n_kaddr_x"、"n_ksize_x",、"ubi0:rootfs rw ubi.mtd=y,2048",。其中,,setenv為U-Boot自帶的函數(shù)[10],y(y=2*x+6)為文件系統(tǒng)所在分區(qū),。
參數(shù)預(yù)處理函數(shù)judge_init()主要工作是調(diào)用setjudge分別設(shè)置r_active_x,、b_success_x為"no",設(shè)置rec_kernel_x,、rec_fs_x,、r_active_y、b_success_y為"yes",。其中,,y=cyc_add(x),函數(shù)cyc_add()為周期相加函數(shù),,即當(dāng)x<MAX_MTD_SYSTEM(系統(tǒng)鏡像區(qū)數(shù)量)時(shí),,x++,否則x=1。
2.3 Linux下備份及恢復(fù)設(shè)計(jì)
在系統(tǒng)鏡像啟動(dòng)之前,,U-Boot已經(jīng)修改了Judge-Area中的參數(shù)并保存到NAND Flash,,那么,Linux下就是對(duì)這些參數(shù)進(jìn)行后期處理,。本文采用開(kāi)機(jī)自啟動(dòng)腳本方式實(shí)現(xiàn)參數(shù)的處理[11],,針對(duì)實(shí)際的應(yīng)用環(huán)境,可以將腳本插入到“不信任”位置,。一旦系統(tǒng)或程序崩潰,,腳本就會(huì)接收到由應(yīng)用程序、內(nèi)核等傳來(lái)的命令,。然后決定是進(jìn)行參數(shù)還原,,還是復(fù)位系統(tǒng)。Linux下備份及恢復(fù)機(jī)制主要就是通過(guò)該腳本實(shí)現(xiàn),,如圖3所示,。
本文使用MTD+UBIFS的方式管理Flash,跳過(guò)FTL/NFTL(Flash轉(zhuǎn)換層/NAND Flash轉(zhuǎn)換層),,大大提高了管理能力[12],。借用mtd-utils工具包中針對(duì)NAND操作的工具[13],可以將Judge-Area(mtd6)區(qū)中的內(nèi)容保存到j(luò)udge.txt文件中,。然后調(diào)用Linux下的sed命令修改標(biāo)志位,,最后將修改后的文件寫回到Judge-Area區(qū)。整個(gè)操作由anti_judge_init腳本完成,,主要工作如下:
mtd_debug read /dev/mtd6 0 $filesize judge.txt
/* 修改參數(shù)old_flag為new_flag */
sed -e "s/$old_flag/$new_flag/g" judge.txt
mtd_debug erase /dev/mtd6 0 $filesize
mtd_debug read /dev/mtd6 0 $filesize judge.txt
為保證NAND分區(qū)一致性,,需要修改內(nèi)核NAND partition信息。內(nèi)核分區(qū)信息存放在mtd_partition結(jié)構(gòu)體中,該文件一般位于arm/arm/plat目錄下,。另外,,制作UBIFS文件系統(tǒng)也要和內(nèi)核分區(qū)保持一致。制作UBIFS鏡像文件,,需要使用mkfs.ubifs工具,,該工具也是mtd-utils工具包中的內(nèi)容[14]。
3 系統(tǒng)測(cè)試
本系統(tǒng)在多款開(kāi)發(fā)板上測(cè)試通過(guò),,以Tiny210開(kāi)發(fā)板上的三重備份與恢復(fù)系統(tǒng)為例,,測(cè)試方法是重新編譯包含自動(dòng)備份與恢復(fù)機(jī)制的u-boot.img、uImage和ubi.img,。ubi.img中加入了視頻監(jiān)控程序,,在該程序中預(yù)留運(yùn)行一段時(shí)間攝像頭就會(huì)打開(kāi)失敗的BUG。因此,,視頻監(jiān)控程序就是本系統(tǒng)“不信任”位置,,如果程序運(yùn)行失敗,就執(zhí)行Linux下的自動(dòng)備份與恢復(fù)機(jī)制,。Tiny210開(kāi)發(fā)板集成了512 MB SLC NAND Flash,,將NAND Flash被分成12個(gè)區(qū)域,見(jiàn)表1,。
進(jìn)入SD卡上的U-Boot,,運(yùn)行updatesys將生成的u-boot.img、uImage,、ubiubi.img燒寫到指定區(qū)域。上電,,系統(tǒng)啟動(dòng)成功,,運(yùn)行視頻監(jiān)控程序一段時(shí)間后,系統(tǒng)自動(dòng)重啟,,在串口上查看到的備份與恢復(fù)信息如圖4所示,。
從打印的信息可以看出,A區(qū)的系統(tǒng)鏡像被B區(qū)覆蓋,,接著運(yùn)行另一個(gè)分區(qū)的系統(tǒng)鏡像,。
4 結(jié)論
從測(cè)試結(jié)果看,本文設(shè)計(jì)的備份與恢復(fù)機(jī)制可以保證系統(tǒng)能在特殊的環(huán)境下穩(wěn)定地工作,,整個(gè)過(guò)程都是系統(tǒng)自動(dòng)完成,,維護(hù)方便。目前,,NAND Flash的成本越來(lái)越低,,容量越來(lái)越大[15],這種備份與恢復(fù)方法無(wú)疑是降低成本,、保證系統(tǒng)穩(wěn)定性方便有效的方法,。該方案可以應(yīng)用在一些對(duì)功能穩(wěn)定性要求高和維護(hù)不方便的系統(tǒng)測(cè)試等場(chǎng)合,。
參考文獻(xiàn)
[1] 索紅軍.嵌入式系統(tǒng)中熱備份雙機(jī)切換技術(shù)研究[J].微計(jì)算機(jī)信息,2008,,24(8):32-34.
[2] 馬錦榮.一種嵌入式系統(tǒng)bootrom自動(dòng)備份及切換技術(shù)[J].單片機(jī)與嵌入式系統(tǒng)應(yīng)用,,2011,11(12):74-75.
[3] 謝長(zhǎng)生,,韓德志,,李懷陽(yáng).容災(zāi)備份的等級(jí)和技術(shù)[J].中國(guó)計(jì)算機(jī)用戶,2003,,19(18):30-31.
[4] 郭榮佐,,黃君.嵌入式實(shí)時(shí)控制系統(tǒng)硬件可靠性及應(yīng)用研究[J].電子技術(shù)應(yīng)用,2012(5):11-14.
[5] 蔡利平,,任家富,,童銳,等.基于ARM的Nand Flash啟動(dòng)分析與移植[J].計(jì)算機(jī)工程與設(shè)計(jì),2012(3):931-935.
[6] 高文輝,,師奕兵,,張偉.基于S3C2440的U-Boot雙啟動(dòng)實(shí)現(xiàn)[J].測(cè)控技術(shù),2012(2):87-91.
[7] 胡勇其,,侯紫峰.嵌入式Linux下NAND存儲(chǔ)系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)工程,,2006(4):61-63,81.
[8] 韋斯,,丁志剛,,張偉宏.LINUX下UBI子系統(tǒng)的研究與應(yīng)用[J].計(jì)算機(jī)應(yīng)用與軟件,2010(10):68-71.
[9] 賈源泉,,肖儂,,賴明澈,等.基于NAND FLASH的多路并行存儲(chǔ)系統(tǒng)中壞塊策略的研究[J].計(jì)算機(jī)研究與發(fā)展,,2012(z1):68-72.
[10] 武貝貝.面向NAND閃存的SQLite數(shù)據(jù)恢復(fù)技術(shù)研究與應(yīng)用[D].浙江:杭州電子科技大學(xué),,2012.
[11] 陳鵬,王樹志,,董孝峰,,等.一種嵌入式操作系統(tǒng)休眠喚醒后程序自動(dòng)運(yùn)行的方法[J].電子技術(shù)應(yīng)用,2012,,38(2):11-13.
[12] 張少波,,徐廣輝,田小鋒,,等.基于Nand FLASH高可靠自恢復(fù)實(shí)時(shí)文件系統(tǒng)[J].計(jì)算機(jī)工程與科學(xué),,2012(6):169-173.
[13] 高麗,張歡慶.嵌入式Linux中NAND Flash設(shè)備驅(qū)動(dòng)研究[J].電腦開(kāi)發(fā)與應(yīng)用,2014(5):11-16.
[14] 鞠高明,,俞建新.UBIFS閃存文件系統(tǒng)分析與研究[J].電腦知識(shí)與技術(shù),,2014(4):749-754.
[15] 魯慧榮.2012年閃存技術(shù)與市場(chǎng)變化趨勢(shì)[J].集成電路應(yīng)用,2013(1):4-6.