【swupdate文檔 一】嵌入式系統的軟件管理
嵌入式系統的軟件管理
嵌入式系統變得越來越復雜, 它們的軟件也反映了這種復雜性的增加。
為了支持新的特性和修復,很有必要讓嵌入式系統上的軟件
能夠以絕對可靠的方式更新。
在基於linux的系統上,我們可以在大多數情況下找到以下元素:
- 引導裝載程序
- 內核和設備樹
- 根文件系統
- 其他在後續掛載的文件系統
- 用戶資料,以裸數據格式存在或者保存在文件系統中
- 特定用途的軟件. 如,用於下載到相連接的微控制器的固件等
一般來說,在大多數情況下是需要更新
內核和根文件系統,保存用戶數據-但實際情況各不相同。
僅在少數情況下,還需要更新引導加載程序,
事實上,更新引導加載程序總是很危險的, 因為更新中的失敗會破壞設備。
但這通常無法由最終用戶完成,即設備需要返廠維修。
關於軟件更新有很多不同的概念。我將解釋其中的一些概念,
然後解釋為什麽我實施了這個項目。
通過引導加載程序完成更新
引導加載程序所做的工作遠不止啟動內核那麽簡單。
它們有自己的shell,且可以使用處理器的外圍設備
進行管理,在大多數情況下是通過串行通訊。 它們通常是可執行腳本的,這使得
實現某種軟件更新機制成為了可能。
然而,我發現這種方法有一些缺點,
這讓我另行尋找基於運行在Linux上的應用程序的解決方案。
引導加載程序對外圍設備的使用有局限性
並不是所有內核中支持的設備都可以在引導加載程序使用。
但將驅動程序移植到引導加載程序中,就並不總是有意義的了。
引導加載程序的驅動程序不會被更新
引導加載程序的驅動程序大多是從Linux內核移植過來的,
但是由於經過調整的原因,它們以後不會被修復或與內核同步,
而bug修復則會定期在Linux內核中進行。
一些外圍設備可能以不可靠的方式工作,
並且修復問題可能並不容易。引導加載程序中的驅動程序
或多或少是內核中相應驅動程序的復刻(fork)。
例如,用於NAND設備的UBI/UBIFS在內核中包含
了許多修復程序,這些修復程序並沒有移植回引導加載程序。
USB協議棧也可以找到相同的情況。支持新外圍設備或協議的工作,
簡化版的文件系統
支持的文件系統的數量是有限的。
將文件系統支持移植到引導加載程序需要付出很大的努力。
網絡支持有限
網絡協議棧是有限的,通常通過一個更新只能通過 UDP但不能通過TCP完成。
與操作人員交互
很難將接口暴露給操作員, 比如瀏覽器中的GUI或顯示器上的GUI。
比起在引導加載程序中,復雜的邏輯可以在應用程序內部更容易實現。
擴展引導加載程序是復雜的,因為所有的服務和庫都不可用。
引導加載程序更新的優點
然而,這種方法也有一些優點:
-更新軟件通常更簡單。
-占用空間更小:即使是一個僅用於軟件管理的獨立應用程序
也需要自己的內核和根文件系統。即使它們的大小能夠被裁剪,
將更新軟件不需要的部分去掉,它們的大小也是不可忽略的。
通過包管理器更新
所有的Linux發行版都使用包管理器做更新, 為什麽這不適用於嵌入式系統?
我不能說它不能被使用,但是使用這種方法有一個重要的缺點。
嵌入式系統是使用特定的軟件進行過良好測試的。
使用包管理器可能會讓人覺得奇怪,因為軟件本身不再是 原子的 ,
而是分裂成一系列包。
我們怎樣才能保證一個能基於庫版本x.y正常工作的應用程序,
同樣也能基於同一個庫的不同版本工作呢?如何才能成功地做好測試?
對於制造商來說,通常更好的說法是發布了一個新的軟件版本
(經過測試工程師的良好測試),並且可以更新新的軟件(或固件)。
對測試人員來說,在包中進行拆分可能會產生噩夢和巨大的工作量。
簡單地替換單個文件可以加快開發速度,
但是對於客戶站點來說,這是一個軟件版本的噩夢。
如果客戶報告了一個bug,那麽在之前已經向客戶發送過
一些文件的補丁時,軟件怎麽可能還算是“2.5版本”呢?
原子更新通常是嵌入式系統的必備特性。
應用程序進行軟件升級的策略
應用程序也可以用於升級系統,而不是使用引導加載程序。
應用程序可以使用操作系統提供的所有服務。
建議的解決方案是一個獨立的軟件,
它遵循客戶規則,執行檢查以確定軟件是否可安裝,
然後將軟件安裝到所需的存儲上。
應用程序可以檢測所提供的新軟件是否適合硬件,
也可以檢查軟件是否由經過驗證的權威機構發布。
支持的特性範圍可以從小型系統擴展到復雜系統,
包括安裝前和安裝後腳本等等。
根據系統的資源,可以使用不同的策略。 下面我將列出其中一些。
雙備份系統 - 支持回退
如果存儲空間足夠保存整個軟件的兩個副本,
那麽即使軟件更新被中斷或斷電,也可以保證始終有一個可用的副本。
每個副本必須包含內核、根文件系統和每個可以更新的組件。
需要一種機制來識別正在運行的版本。
SWUpdate應該集成到應用程序軟件中, 當需要更新時,應用程序軟件將觸發它。
SWUpdate的職責是更新備用副本, 不修改正在運行的軟件副本。
與引導加載程序的協作通常是必要的,
因為引導加載程序必須決定應該啟動哪個副本。
同樣,必須能夠在兩個副本之間進行切換。
重新啟動後,引導加載程序決定應該運行哪個副本。
請參閱有關引導加載程序的章節,
了解可以實現哪些機制來確保更新後目標不會被破壞。
最明顯的缺點是所需的空間量。 每個副本的可用空間小於存儲空間的一半。
然而,即使在斷電的情況下,更新也總是安全的。
這個項目支持這個策略。
作為該項目一部分的應用程序應該安裝在根文件系統中,
並根據需要啟動或觸發。不需要額外的內核,
因為這兩個副本保證總是可以升級不運行的副本。
SWUpdate將設置bootloader變量以通知新映像已成功安裝。
單系統 - 以獨立鏡像形式運行
軟件升級應用程序由內核(可裁剪掉不必要的驅動等)
和一個小的根文件系統以及應用程序及其庫組成。
整個大小遠遠小於系統軟件的一個副本。
根據設置,這個獨立根文件系統的大小從 2.5MB 到 8MB 不等。
如果說大小對於小型系統非常重要,
那麽對於具有大量存儲或大容量NAND的系統, 其大小則可以忽略不計。
系統可以進入 "升級" 模式,只需向引導加載程序發出必須啟動升級軟件的信號。
具體方法可能有所不同,例如設置引導加載程序環境或使用和外部GPIO。
引導加載程序啟動“SWUpdate”,
引導SWUpdate內核並將initrd映像作為根文件系統。
因為它在RAM中運行,所以可以升級整個存儲。
與雙拷貝策略不同,系統必須重新啟動以將其自身置於更新模式。
這個方案比起使用兩個副本,占用的存儲空間更少,
但是它不能保證在不再次更新軟件的情況下進行回退。
不過,至少它可以保證,當主應用不存在或損壞時,
以及當升級過程由於某種原因而中斷時,系統自動進入升級模式。
事實上,可以將升級過程視為事務,
只有成功升級後,新軟件才設置為“可引導”。
考慮到這些因素,使用此策略進行升級是安全的: 如果舊軟件損壞或無法運行,
始終確保系統啟動並準備好獲得新軟件。
使用U-Boot作為引導加載程序, SWUpdate能夠管理U-Boot的環境設置變量,
以指示事務的開始和結束,以及包含有效的軟件的存儲區域。
針對GRUB環境塊修改和EFI引導保護的類似特性也已被引入。
SWUpdate主要以如下配置的方式使用。
Yocto生成包含SWUpdate應用程序的initrd映像,
該映像在掛載根文件系統之後自動啟動。
有些事情出錯了 ?
許多事情都可能出錯,必須保證系統能夠再次運行,
並且可能能夠重新加載新的軟件來修復損壞的映像。
SWUpdate與引導加載程序一起工作,以識別失敗的可能原因。
目前支持U-Boot、GRUB和EFI引導保護。
我們至少可以列出一些常見的原因:
-安裝過程中鏡像損壞。
: SWUpdate能夠識別它,並且更新過程會被中止。
舊的軟件被保存下來,沒有任何東西被真正復制到目標的存儲中
- 存儲(flash)中損壞的鏡像
- 遠程更新由於通信問題而中斷
- 意外掉電
SWUpdate的工作流程是事務性的。引導加載程序的環境變量“recovery_status”
被設置為向引導加載程序發出更新狀態的信號。
當然,還可以添加更多變量,用於微調和報告錯誤原因。
recovery_status可以取值為“progress”,“failed”,或者它也可以被取消設置。
當SWUpdate啟動時,它將recovery_status設置為“progress”。
更新成功完成後,變量將被刪除。如果更新以錯誤結束,
recovery_status的值為“failed”。
當更新被中斷時,不管什麽原因,引導加載程序都能識別到,
因為recovery_status變量處於“progress”或“failed”狀態。
然後,引導加載程序可以再次啟動SWUpdate,以再次
加載軟件(單副本情況)或運行應用程序的舊副本(雙副本情況)。
意外掉電
如果發生斷電,必須保證系統能夠再次工作 —— 重新
啟動SWUpdate或恢復軟件的舊副本。
一般情況下,行為可以根據所選擇的場景進行劃分:
單拷貝:SWUpdate被中斷,更新事務沒有以成功結束。
引導加載程序能夠再次啟動SWUpdate,從而有可能再次更新軟件。雙拷貝:SWUpdate沒有在備份系統和當前系統之間做切換。
當前版本的軟件,並沒有被更新觸及到,會再次啟動。
為了完全安全,SWUpdate和引導加載程序需要交換一些信息。
引導加載程序必須檢測更新是否由於斷電而中斷,
並重新啟動SWUpdate,直到更新成功。
SWUpdate支持U-Boot、GRUB和EFI Boot Guard引導加載程序。 U-Boot和EFI Boot
Guard有用於保證掉電安全的環境變量,
SWUpdate能夠讀取和更改這些變量,以此與引導加載程序通信。
對於GRUB,則使用固定的1024字節環境變量塊文件。
SWUpdate在開始更新系統時設置一個變量作為標誌,
並在完成之後重置同一變量。引導加載程序可以讀取此標誌,
以檢查在上次關機之前是否正在運行更新。
升級SWUpdate本身會如何?
SWUpdate被認為用於整個開發過程,代替定制過程以在開發過程中更新軟件。
在投產前,SWUpdate被針對這個項目進行過很好的測試。
如果SWUpdate本身應該被更新,那麽當存儲中只有一個SWUpdate副本時,
更新就不是安全的。只有當SWUpdate擁有兩個副本時,才能保證安全更新。
如果SWUpdate是升級映像的一部分,則有一些方法可以避免這個問題:
- 有兩份SWUpdate
- 承擔風險,但準備一個在引導加載程序中可使用的救援程序。
升級引導加載程序會如何?
更新引導加載程序在大多數情況下無法做到的。
在大多數SOC上,不存在多個引導加載程序的副本,
當引導加載程序被破壞時,板子就無法引導啟動了。
一些soc允許擁有多個引導加載程序副本。
但同樣,沒有通用的解決方案,因為它是 非常 特定於硬件的。
根據我的經驗,大多數產品不允許更新引導加載程序。
當產品準備好量產時,還必須要更新引導加載程序,這種情況是非常少見的。
以上結論不適用於更新U-Boot環境變量,這是一種常見的情況。
U-Boot提供整個環境變量的兩個副本,從SWUpdate中更新環境是
掉電安全的。其他引導加載程序則不一定具有此功能。
註:
本文地址 https://www.cnblogs.com/zqb-all/p/10090280.html
譯自 swupdate 文檔 https://sbabic.github.io/swupdate/overview.html
有更新會在github上發布 https://zqb-all.github.io/swupdate/overview.html
【swupdate文檔 一】嵌入式系統的軟件管理