嵌入式Linux文件系統知多少


Nand/Nor Flash

在嵌入式Linux產品中,通常使用的存儲介質為Nand Flash和Nor Flash,而手機、相機等產品通常使用eMMC、SD Card作為存儲介質,導致這種差異的原因主要是成本考量。

Nand Flash和Nor Flash具有低成本、高密度存儲的優勢。但是,它們在讀寫操作上又有各自的限制。Nand Flash和Nor Flash都沒有片內FTL(Flash Transfer Layer)層,換句話說,它們都是raw flash。也就是說,本質上它們都是字符設備。未填寫數據的時候,所有位都是高電平;寫操作是將高電平變為低電平;只有擦操作才能將低電平變為高電平。所以Nand Flash和Nor Flash的寫操作都只能通過先擦除再寫入完成,讀操作沒有限制。

Nand Flash通常用來存儲數據,它通過頁(Page)和塊(Block)兩級結構組成,頁大小通常為512Byte,類似於磁盤,塊大小為8~32KB。讀取和寫入以頁為單位進行,擦操作以塊為單位進行。另外,針對每一頁有16字節的OOB區,用來存放額外的信息以及ECC糾錯碼。Nand Flash比較容易出現壞塊,其生命周期是擦寫100萬次。

Nor Flash通常用來存代碼,因為它具有XIP(eXecute In Place)的特性,即片上執行,CPU可以把它當RAM使用,同時它也可以保存數據。Nor Flash的頁大小通常為32Byte,塊大小為128KB,芯片內部包含512Byte的寫緩沖區。Nor Flash具有隨機讀和頁讀兩種方式,擦除操作則是以塊為單位,即128KB。Nor Flash在擦除操作之前,必須對每一位寫0。Nor Flash的讀速度比Nand Flash快,擦除和寫入速度則比Nand Flash慢。另外,Nor Flash沒有芯片內部的壞塊處理,因為它比較少出現壞塊,其生命周期是擦寫10萬次。

 

MTD(Memory Technology Devices) 

MTD子系統在raw flash上提供了一層抽象層,並提供統一的API接口給文件系統層,這樣文件系統就不用關心實際的Flash類型是Nand Flash還是Nor Flash。

MTD子系統有以下三種接口:

1) mtd字符設備:/dev/mtd0, /dev/mtd1等,通常包括一組ioctl進行讀取、擦除、寫入、標記壞塊、獲取flash信息等操作

2) sysfs 參考Documentation/ABI/testing/sysfs-class-mtd

3) /proc/mtd

MTD子系統給文件系統層提供的API都在include/linux/mtd/mtd.h中描述,其中最重要的是mtd_info結構體。內核3.4版本之前,文件系統層通過mtd_info的成員函數指針調用接口函數;內核3.4版本以后,通過mtd.h文件中聲明的mtd_read() mtd_write()等函數實現。

MTD既可以是字符設備,也可以是塊設備。

mtdblock驅動是一個過時的工具,用來在mtd設備之上模擬塊設備。它不進行壞塊處理,所以不能用於Nand Flash。它的工作原理是通過緩存數據塊來實現,修改操作在內存中緩存的數據塊進行,然后擦除實際物理塊,再將緩存的數據寫入物理塊。這樣會出現掉電的時候,數據丟失的現象。另外,它也不進行wear-leveling和bit-flips(位反轉)處理。通常將mtdblock理解為FTL層,其實這種認知是錯誤的,盡量不要使用mtdblock,除非你知道自己在干什么。

 

YAFFS/JFFS2/SQUASHFS/UBIFS

文件系統

 

mkimage

uboot源代碼的tools/目錄下有mkimage工具,這個工具可以用來制作不壓縮或者壓縮的多種可啟動映象文件。

為什么uboot下會有這個工具呢?因為bootloader的類型有很多種,不同的bootloader在加載和啟動內核時的方式大體上一致,但是具體實施上有細微的區別,mkimage的目的是在linux內核鏡像文件(zImage)的基礎上加上一段uboot可以識別的頭部信息用來解析和加載內核鏡像,通常最終生成的鏡像文件名為uImage。該頭部信息大小為0x40字節,記錄mkimage參數所指定的信息,比如CPU體系結構、OS類型、鏡像文件類型、內核鏡像加載到內存的地址、壓縮格式等。

Usage: ./mkimage -l image
          -l ==> list image header information
       ./mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
          -A ==> set architecture to 'arch'
          -O ==> set operating system to 'os'
          -T ==> set image type to 'type'
          -C ==> set compression type 'comp'     //壓縮格式,可選none/gzip/bzip2
          -a ==> set load address to 'addr' (hex)    //內核加載到內存的地址
          -e ==> set entry point to 'ep' (hex)      //內核加載到內存的地址+0x40       (跳過0x40的頭部,該參數可以忽略)
          -n ==> set image name to 'name'
          -d ==> use image data from 'datafile'
          -x ==> set XIP (execute in place)
       ./mkimage [-D dtc_options] -f fit-image.its fit-image
       ./mkimage -V ==> print version information and exit

參數說明:
-A 指定CPU的體系結構:
取值 表示的體系結構
alpha Alpha
arm A RM
x86 Intel x86
ia64 IA64
mips MIPS
mips64 MIPS 64 Bit
ppc PowerPC
s390 IBM S390
sh SuperH
sparc SPARC
sparc64 SPARC 64 Bit
m68k MC68000
-O 指定操作系統類型,可以取以下值:
openbsd、netbsd、freebsd、4_4bsd、linux、svr4、esix、solaris、irix、sco、dell、ncr、lynxos、vxworks、psos、qnx、u-boot、rtems、artos
-T 指定映象類型,可以取以下值:
standalone、kernel、ramdisk、multi、firmware、、filesystem
-C 指定映象壓縮方式,可以取以下值:
none 不壓縮
gzip 用gzip的壓縮方式
bzip2 用bzip2的壓縮方式
-a 指定映象在內存中的加載地址,映象下載到內存中時,要按照用mkimage制作映象時,這個參數所指定的地址值來下載
-e 指定映象運行的入口點地址,這個地址就是-a參數指定的值加上0x40(因為前面有個mkimage添加的0x40個字節的頭)
-n 指定映象名
-d 指定制作映象的源文件

示例:mkimage -n 'linux-2.6.14' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -d zImage zImage.img

 

vmlinux/Image/zImage

LD      vmlinux                          內核編譯完成之后,鏈接各目標文件,生成ELF格式vmlinux
SYSMAP  System.map
  SYSMAP  .tmp_System.map
  OBJCOPY
arch/arm/boot/Image                通過objcopy提取vlinux中的代碼段和數據段並打包生成arch/arm/boot/Image
  Kernel:
arch/arm/boot/Image is ready
  AS      arch/arm/boot/compressed/head.o
  GZIP   
arch/arm/boot/compressed/piggy.gz
  AS      arch/arm/boot/compressed/piggy.o
  CC     
arch/arm/boot/compressed/misc.o
  AS     
arch/arm/boot/compressed/head-xscale.o
  LD     
arch/arm/boot/compressed/vmlinux       通過gzip壓縮arch/arm/boot/Image並添加解壓程序等生成ELF格式的arch/arm/boot/compressed/vmlinux
  OBJCOPY
arch/arm/boot/zImage      通過objcopy提取arch/arm/boot/compressed/vmlinux中的代碼段和數據段生成可以放在內存任意地址直接執行的arch/arm/boot/zImage

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM