Linux ubi子系統原理分析

来源:https://www.cnblogs.com/gmpy/archive/2019/05/16/10874475.html
-Advertisement-
Play Games

Linux ubi子系統原理分析,包括概念的澄清,壞塊標誌原理,管理開銷等 ...


本文思維導圖總綱:
思維導圖總綱

綜述

關於ubi子系統,早已有比較正式的介紹,也提供非常形象的介紹ubi子系統ppt
國內的前輩 alloysystem 不辭辛勞為我們提供了部分正式介紹的中文譯文,以及找不到原文的轉載譯文

感謝這些資料讓我迅速入門ubi,進而整理出這博文

此博文是對上文的總結以及中文譯文的補充

在閱讀本文之前,建議先學習PPT中文譯文

概念對比

UBI Vs. MTD

UBI層次

上圖非常形象地描述了從Flash到UBIFS的各個層次。從上圖我們發現,MTD子系統在實際的Flash驅動之上 ,而UBI子系統則在MTD子系統之上。

要對比UBI和MTD的概念,我們不妨問自己一個問題,UBI和MTD兩個不同的層次的"使命"分別是什麼?

Flash驅動直接操作設備,而MTD在Flash驅動之上,向上呈現統一的操作介面。所以MTD的"使命"是 屏蔽不同Flash的操作差異,向上提供統一的操作介面

UBI基於MTD,那麼UBI的目的是什麼呢? 在MTD上實現nand特性的管理邏輯,向上屏蔽nand的特性

nand有什麼特性呢?
(下文描述的 Nand驅動,是廣義上的操作Nand的集合,包括fs/ubi/mtd的層次,而非純粹的nand驅動)

1. 操作最小單元為頁(Page)/塊(Block)
    Nand不同於Nor,Nor可以以位元組為單位操作Flash,但Nand的讀寫最小單元是頁,擦除最小單元是塊。
    對常見的1Gbit的spinand而言,其頁大小2KBytes,塊大小是128K,表示一個塊有64個頁。
2. 擦除壽命限制
    Nand的物理性質決定了其每個塊都有擦除壽命的限制,SLC約10W次,MLC約5000次,TLC約1000次。
    因此,Nand驅動必須要做到磨損平衡。
    所謂磨損平衡,就是儘可能均衡使用每一個塊,既不讓一個塊太大壓力,也不讓一個塊太過空閑。
3. 位翻轉(bit-flips)
    Nand的物理性質使其可能會在使用、保存過程中出現位翻轉的現象。
    例如,原始數據為0xFFFC,在存儲過程中Flash的數據卻變成了0xFFFF。
    所以要不在nand內部,要不在nand控制器都會存在ecc校正模塊,在位翻轉後校正。
    然而,ecc並不是萬能的,其校正能力有限,所以驅動必須在位翻轉數量進一步變多之前把數據搬移到其他塊。
    萌新可能會有疑問,ecc都已經校正了為什麼還要搬移?因為ecc校正的是從Flash中讀到記憶體中的數據,
    而不是Flash本身存儲的數據,換句話說,此時Flash中的數據依然是錯的,如果不搬移,隨著翻轉的位數量積累,
    ecc就校正不了了,此時就相當於永久丟失正確數據了。
4. 存在壞塊(Bad Block)
    製作工藝和Nand本身的物理性質,導致在出廠和正常使用過程中都會產生壞塊。
    所謂壞塊,就是說這個塊已經損壞,不能再用於存儲數據,因此Nand驅動需要能自動跳過壞塊。

關於SLC/MLC/TLC的比較,可參考這篇博客

UBI Vs. UBIFS

如果說UBI在MTD之上,在FS之下的中間層,用於抽象MTD屏蔽nand差異,那麼ubifs就是正兒八經的文件系統。
ubifs是基於UBI子系統的文件系統,實現文件系統該有的所有基本功能,例如文件的實現,例如日誌的實現。

這裡需要特別註意的是,ubifs跟jffs/yaffs相比,並不包含nand特性的管理,而是交由ubi來實現。

UBI Vs. Block Layer

Block Layer是適用於常見塊設備的通用塊層,其特有的概念有bio、request、電梯演算法等,其典型的設備有磁碟、SSD、mmc等。
而ubi基於mtd,雖然能模擬塊設備,從本質上來講其並不是塊設備。跟蹤UBIFS的IO操作,發現其IO操作並不經過通用塊設備層。

UBI Vs. FTL

FTL(Flash Translation Layer)是一個"黑盒子",其跟UBI非常像,都是對nand特性進行封裝。

按我的理解,UBI跟FTL的目標不同,導致其實現上會有差異。UBI屏蔽nand特性是為了對接UBIFS,而FTL則是為了對接Block Layer。例如MMC其實也是封裝起來的Nand,只不過在MMC內部實現了FTL,經過FTL的轉換就能以塊設備層的方法直接操作Nand,就能在mmc上格式化常見的塊文件系統,例如EXT、VFAT等。

UBI Volume Vs. UBI Device

在UBI中還有兩個概念,分別是UBI捲(UBI Volume)和UBI設備(UBI Device)。這兩個概念,我們可以這麼理解:

UBI設備 相當於 磁碟設備(sda,mmcblk0)
UBI捲 相當於 磁碟上對應分區(sda1,mmcblk0p1)

換句話說,UBI設備是在MTD設備上創建出來的設備,而UBI捲則是從UBI設備上劃分出來的分區, 從設備節點名(ubi0)和捲名(ubi0_3)可以看出端倪。

上面的描述是為了方便理解UBI捲和UBI設備,實際上UBI捲和分區的概念之間還是有差別的。

LEB Vs. PEB

在UBI子系統中,還有LEB和PEB的概念:

LEB指Logical Erase Block,即邏輯擦除塊,簡稱邏輯塊,表示邏輯捲中的一個塊
PEB指Physical Erase Block,即物理擦除塊,簡稱物理塊,表示物理Nand中的一個塊

為什麼要劃分邏輯塊和物理塊?從PPT中我們可以發現,物理塊和邏輯塊存在動態映射關係,且由於UBI頭的存在,邏輯塊一般會比物理塊小2個頁。

UBI子系統扮演的角色及其作用

UBI子系統就是ubifs與mtd之間的中間層,其向下連接MTD設備,實現nand特性的管理邏輯,向上呈現無壞塊的捲。

所以UBI子系統的作用,主要包括兩點:

1. 屏蔽nand特性(壞塊管理、磨損平衡、位翻轉)
2. UBI捲的實現

UBI捲的邏輯擦除塊(LEB)與物理擦除塊(PEB)之間是動態映射的,詳細可以看PPT

UBI相關的工具

ubi的工具集成在包mtd-utils中,分別有以下工具及其作用

工具 作用
ubinfo 提供ubi設備和捲的信息
ubiattach 鏈接MTD設備到UBI並且創建相應的UBI設備
ubidetach ubiattach相反的操作,將MTD設備從UBI設備上去鏈接
ubimkvol 從UBI設備上創建UBI捲
ubirmvol 從UBI設備上刪除UBI捲
ubiblock 管理UBI捲上的block
ubiupdatevol 更新捲,例如OTA直接更新某個分區鏡像
ubicrc32 使用與ubi相同的基數計算文件的crc32
ubinize 製作UBI鏡像
ubiformat 格式化空的Flash設備,擦除Flash,保存擦除計數,寫入UBI鏡像到Flash
mtdinfo 報告從系統中找到的UBI設備的信息

UBI頭部

UBI子系統需要往每個物理塊的開頭寫入兩個關鍵數據,這兩個關鍵數據就叫做UBI的頭部。

這兩個數據分別是 此物理塊擦除次數頭此物理塊的邏輯捲標記頭,也分別稱為 EC頭(Erase Count)VID頭(Volume IDentifier)

不管是EC頭還是VID頭,都是64Bytes,分別記錄與Nand塊的第一個頁和第二個頁。

以Q&A的形式介紹UBI頭:

Q:為什麼要這兩個頭?  
A:前文有說道,nand每個block有擦除壽命限制,因此需要記錄擦除次數,以實現磨損平衡,因此需要EC頭。此外,為了實現捲,必須記錄捲的邏輯塊與物理塊之間的映射關係,因此需要VID頭。

Q:為什麼不合併成1個頭?
A:兩者寫入的時機不一致,導致兩個頭必須分開寫入。EC頭在每次擦除後,必須馬上寫入以避免丟失,而VID頭只有在映射捲後才會寫入。

Q:不管是EC頭還是VID頭都是64B,為什麼要用2個Page?  
A:使用2個Page是對Nand來說的。前文有說過,Nor的讀寫最小單元是Byte,而Nand的讀寫最小單元是Page,因此對Nor可以只使用64Bytes,對Nand則必須使用2個Page,就是說,即使只有64Bytes有效數據,也需要用無效數據填充滿1個Page一次性寫入。

Q:在記錄擦除次數時掉電等,導致丟失實際擦除次數怎麼辦?  
A:取所有物理塊的擦除次數的平均數

關於UBI頭部的詳細介紹,可參考鏈接

UBI捲表(UBI Volume Table)

UBI子系統有個對用戶隱藏的特殊捲,叫層捲(layout volume),用來記錄捲表。我們可以把捲表等價於分區表,記錄各個捲的信息。捲表大小為2個邏輯擦除塊,每個邏輯擦除塊記錄一份捲表,換句話說,UBI子系統為了保證捲表的可靠性,用2個邏輯記錄2分捲標信息。

由於層捲的大小是固定的(2個邏輯塊),導致能保存的捲信息受限,所以最大支持的捲數量是隨著邏輯塊的大小改變而改變的,但最多不超過128個。

捲表中每個捲都保存了什麼信息?

struct ubi_vtbl_record {                                                         
        __be32  reserved_pebs; //物理塊數量
        __be32  alignment; //捲對齊
        __be32  data_pad;                                                        
        __u8    vol_type; //靜態捲or動態捲標識
        __u8    upd_marker; //更新標識
        __be16  name_len; //捲名長度
        __u8    name[UBI_VOL_NAME_MAX+1]; //捲名
        __u8    flags; //常用語自動重分配大小標記
        __u8    padding[23]; //保留區域
        __be32  crc; //捲信息的CRC32校驗值
} __packed;

由這個結構體我們可以發現,捲信息是被CRC32保護著的。比較有意思的有兩個成員:vol_type 和 flags

動態捲 & 靜態捲

vol_type成員標記了捲的類型,在創建捲時指定,可選動態捲和靜態捲。那麼什麼是動態捲?什麼又是靜態捲?

動態捲和靜態捲是兩種捲的類型,靜態捲標記此捲只讀,於是UBI子系統使用CRC32來校驗保護整個捲的數據,動態捲是可讀寫的捲,數據的完整性由文件系統來保證。

關於靜態捲和動態捲的介紹,可參考鏈接

更新標識

flags成員常用於標識是否自動重分配大小。怎麼樣自動充分配大小呢?在首次運行時自動resize捲,讓捲大小覆蓋所有未使用的邏輯塊。

例如Flash大小是128M,在燒錄的鏡像中分配的所有捲加起來只用了100M,如果有捲被表示為autoresize,那麼在首次運行時,那個捲會自動擴大,把剩餘的28M囊括在內。

這個功能挺實用的,例如某個方案規劃中,除去rootfs、內核等必要空間外,把剩餘所有空間儘可能分配給用戶數據分區。
在開發過程中加了個應用,導致rootfs捲需要更大的空間,進而需要壓縮user_data捲的空間。
如果user_data空間是autoresize的,那麼user_data捲的空間就會自動壓縮。

再例如舊方案用的是128M的nand,後面升級為256M,即使使用相同的固件,也不用擔心多出來的128M浪費掉了,
因為user_data捲自動擴大囊括多出來的128M。

需要註意的是,只允許1個捲設置autoresize標誌

關於更新標識更多的介紹,參考鏈接

壞塊標記

我們知道Nand的物理性質,導致在使用久之後會產生壞塊,那麼UBI是如何判斷好塊是否變成了壞塊的呢?

有兩個場景可能會標識壞塊,分別是寫失敗和擦除失敗。擦除失敗且返回是EIO,則直接標記壞塊。比較有意思的是寫失敗的判斷邏輯。

UBI子系統有後臺進程對疑似的壞塊進行"嚴刑拷打"(torturing),有5個步驟:

1. 擦除嫌疑壞塊
2. 讀取擦除後的值,判斷是否都是0xFF(擦除後理應全為0xFF)
3. 寫入特定數據
4. 讀取並校驗寫入的數據
5. 以不同的數據模式重覆步驟1-4

如果"嚴刑拷打"出問題,則標記壞塊,詳細的實現邏輯可參考函數torture_peb()

原文可參考鏈接

UBI管理開銷

什麼是管理開銷呢?為了管理Nand的空間,實現磨損平衡、壞塊管理等等功能,必須占用一部分空間來存儲關鍵數據,就好像文件系統的元數據。管理占用的空間是不會呈現給用戶空間使用的,這空間即為管理的開銷。

對Nand來說,UBI管理開銷主要包含5個部分:

1. 層捲(捲表) : 占用兩個物理塊
2. 磨損平衡:占用一個物理塊
3. 邏輯塊修改原子操作:占用一個物理塊
4. 壞塊管理:預設每1024個塊則預留20個塊(內核參數可配:CONFIG_MTD_UBI_BEB_LIMIT)
5. UBI頭:(物理塊總數*2)個頁

壞塊管理預留的塊數量,也可以理解為最大能容納多少個壞塊;再考慮壞塊的存在,管理開銷計算公式為:

UBI管理總開銷 = 特性開銷 + UBI頭開銷

其中:
壞塊預留 = MAX(壞塊數量,壞塊管理預留數量)
特性開銷 = (壞塊預留 + 1個磨損平衡開銷 + 1個原子操作開銷 + 2個層捲開銷) * 物理塊大小
UBI頭開銷 = 2 * 頁大小 * (含壞塊的總塊數 - 壞塊預留 - 1個磨損平衡開銷 + 1個原子操作開銷 + 2個層捲開銷)

也就是說:
UBI管理總開銷 = (壞塊預留 + 4) * 物理塊大小 + 2 * 頁大小 * (含壞塊的總塊數 - 壞塊預留 - 4)

以128M的江波龍的FS35ND01G-S1F1 SPI Nand為例,其規格為:

總大小:128M(1Gbit)
頁大小:2K bytes
塊大小:128K
塊數量:1024

假設是完全無壞塊的片子,其管理開銷為:

UBI管理開銷 = (20 + 4) * 128K + 2 * 2K * (1024 - 20 - 4) = 7072K ≈ 7M

詳細參考原文鏈接


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在終端輸入: 即可得解。 ...
  • [toc] Linux目錄配置的依據 FHS 因為利用Linux來開發產品的公司太多,例如,CentOS、Ubuntu、ReHat...,導致了配置文件存放的目錄沒有統一的標準。後來就有了FHS(Filesystem Hierarchy Standard)的標準出來了。 四種交互作用的形態 1.可分 ...
  • 1.上傳或下載nginx軟體包,並解壓 2.搭建nginx安裝環境 3.進入解壓後的目錄,預編譯操作 3.編譯並安裝 ...
  • 簡介 在Linux的早期時代(也許吧?我猜的。也可能是Unix。),想要在系統上安裝一款應用程式,是比較複雜的。需要專業的人員自行獲取程式的源代碼,並且編譯安裝,這是非常的複雜且需要一定的專業功底的,這種方式叫做源碼編譯安裝(後面會描述)。 再後來就有人/組織將這個過程簡化了,他們將事先已經編譯好的 ...
  • 【轉載】原文:https://blog.csdn.net/u013091013/article/details/68941250 通常情況下,我門在同一臺伺服器拷貝數據最常用的命令便是cp,如果要在不同伺服器之間拷貝的話可以用scp命令。1、命令格式:scp [參數] [原路徑] [目標路徑]或者s ...
  • 查找錯誤日誌顯示:/html/group1/M00/00/00/wKjJWFzdF0qAE1pBAACmOw57Lw0520_big.jpg" failed (2: No such file or directory), client: 10.10.28.124, server: 192.168.2 ...
  • 即時編譯(JIT : just-in-time compilation): 指電腦領域里,即時編譯也被成為動態翻譯,是一種通過在運行時將位元組碼翻譯為機器碼,從而改善位元組碼編譯語言性能的技術 即時編譯前期的兩個運行時理論是位元組碼編譯和動態編譯 比如Java,通常是先將源碼編譯成稱為中間語言的位元組碼, ...
  • vim 有三種模式,註意:這三種模式有很多不同的叫法,我這裡是按照鳥哥的linux書中的叫法。 一般指令模式、編輯模式、指令列命令模式 1.vim 文件名 進入一般模式; 2.按 i 進行編輯 進入編輯模式 ;(或者I, o, O, a, A, r, R) 3.編輯結束,按ESC 鍵 跳到一般模式模 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...