MTD應用學習:mtd和mtdblock的區別

今天作升級方案用到了mtd-utils中的flash_eraseall和flash_cp兩個工具,在進行方案驗證的時候,遭遇到各類不解和疑惑,因對MTD的原理不熟悉,因此只能屢次嘗試,雖然最後把方案搞定了,不過以爲MTD中的mtd和mtdblock區別這塊仍是值得總結學習一下。這裏先說明一下問題現象,而後在進行具體的區別原理解釋。 shell

MTD設備(Nor Flash)使用中的問題現象表現

  1. mtd-utils工具對mtd和mtdblock分區設備的區別處理
  2. / $ flash_eraseall /dev/mtdblock/2
    flash_eraseall: /dev/mtdblock/2: unable to get MTD device info
    / $ flash_eraseall /dev/mtdblock/2
    flash_eraseall: /dev/mtdblock/2: unable to get MTD device info
    / $ flash_eraseall /dev/mtd/2
    Erasing 128 Kibyte @ 8e0000 -- 98 % complete.
    / $ ls
    / $ flashcp rootfs_version /dev/mtdblock2
    This doesn't seem to be a valid MTD flash device!
    / $ flashcp rootfs_version /dev/mtdblock/2
    This doesn't seem to be a valid MTD flash device!
    / $ flashcp rootfs_version /dev/mtd2
    / $ ls
  3. mtd和mtdblock分區設備mount時的區別
  4. / $ mount -t jffs2 /dev/mtd/2 qqzm/
    mount: Mounting /dev/mtd/2 on qqzm/ failed: Invalid argument
    / $ mount -t jffs2 /dev/mtd2 qqzm/
    mount: Mounting /dev/mtd2 on qqzm/ failed: Invalid argument
    / $ mount -t jffs2 /dev/mtdblock/2 qqzm/
    / $ ls
  5. mtdblock掛載成功,單擦除後卸載失敗
  6. / $ flash_eraseall /dev/mtd/2  Erasing 128 Kibyte @ 8e0000 -- 98 % complete.
    /qqzm $ mount
    /dev/root on / type jffs2 (rw,noatime)
    proc on /proc type proc (rw,nodiratime)
    sysfs on /sys type sysfs (rw)
    devfs on /dev type devfs (rw)
    devpts on /dev/pts type devpts (rw)
    /dev/mmcblk0p1 on /mnt/sd type vfat (rw,nodiratime,fmask=0022,dmask=0022,codepage=cp437,iocharset=iso8859-1)
    /dev/mtdblock/2 on /qqzm type jffs2 (rw,noatime)
    none on /qqzm/www/cgi-bin/tmp type ramfs (rw)
    /qqzm $ cd ..
    / $ umount /qqzm
    umount: Couldn't umount /qqzm: Inappropriate ioctl for device
    / $ umount /dev/mtdblock/2
    umount: Couldn't umount /dev/mtdblock/2: Inappropriate ioctl for device
    / $

經過上面的不斷嘗試和錯誤反饋,我把方案基本驗證經過了,只是對其中的原理不清楚: 架構

  • 爲何mtd和mtdblock明明是同一個設備分區卻有不一樣的操做?
  • mount命令只能掛載塊設備嗎?
  • 卸載mtdblock設備時,Inappropriate ioctl for device是什麼意思?
  • unable to get MTD device info,又是什麼意思?

MTD技術的基本原理

MTD(memory technology device內存技術設備)是用於訪問memory設備(ROM、flash)的Linux的子系統。MTD的主要目的是爲了使新的memory設備的驅動更加簡單,爲此它在硬件和上層之間提供了一個抽象的接口,並進行了一個層次劃分,層次從上到下大體爲:設備文件、MTD設備層、MTD原始設備層、硬件驅動層。MTD的全部源代碼在/drivers/mtd子目錄下。 app

系統中的MTD設備文件

~ $ ls /dev/mtd* -l
crw-rw----    1 root     root      90,   0 Jan  1 00:00 /dev/mtd0
crw-rw----    1 root     root      90,   1 Jan  1 00:00 /dev/mtd0ro
crw-rw----    1 root     root      90,   2 Jan  1 00:00 /dev/mtd1
crw-rw----    1 root     root      90,   3 Jan  1 00:00 /dev/mtd1ro
crw-rw----    1 root     root      90,   4 Jan  1 00:00 /dev/mtd2
crw-rw----    1 root     root      90,   5 Jan  1 00:00 /dev/mtd2ro
crw-rw----    1 root     root      90,   6 Jan  1 00:00 /dev/mtd3
crw-rw----    1 root     root      90,   7 Jan  1 00:00 /dev/mtd3ro
brw-rw----    1 root     root      31,   0 Jan  1 00:00 /dev/mtdblock0
brw-rw----    1 root     root      31,   1 Jan  1 00:00 /dev/mtdblock1
brw-rw----    1 root     root      31,   2 Jan  1 00:00 /dev/mtdblock2
brw-rw----    1 root     root      31,   3 Jan  1 00:00 /dev/mtdblock3

/dev/mtd:
crw-rw-rw-    1 root     root      90,   0 Jan  1 00:00 0
cr--r--r--    1 root     root      90,   1 Jan  1 00:00 0ro
crw-rw-rw-    1 root     root      90,   2 Jan  1 00:00 1
cr--r--r--    1 root     root      90,   3 Jan  1 00:00 1ro
crw-rw-rw-    1 root     root      90,   4 Jan  1 00:00 2
cr--r--r--    1 root     root      90,   5 Jan  1 00:00 2ro
crw-rw-rw-    1 root     root      90,   6 Jan  1 00:00 3
cr--r--r--    1 root     root      90,   7 Jan  1 00:00 3ro

/dev/mtdblock:
brw-------    1 root     root      31,   0 Jan  1 00:00 0
brw-------    1 root     root      31,   1 Jan  1 00:00 1
brw-------    1 root     root      31,   2 Jan  1 00:00 2
brw-------    1 root     root      31,   3 Jan  1 00:00 3
~ $
能夠看到有mtdN和對應的/dev/mtd/N、mtdblockN和對應的/dev/mtdblock/N兩類MTD設備,分別是字符設備,主設備號90和塊設備,主設備號31。其中/dev/mtd0和/dev/mtd/0是徹底等價的,/dev/mtdblock0和/dev/mtdblock/0是徹底等價的,而/dev/mtd0和/dev/mtdblock0則是同一個MTD分區的兩種不一樣應用描述,操做上是有區別的。

/dev/mtdN設備

/dev/mtdN 是MTD架構中實現的mtd分區所對應的字符設備(將mtd設備分紅多個區,每一個區就爲一個字符設備),其裏面添加了一些ioctl,支持不少命令,如MEMGETINFO,MEMERASE等。 工具

mtd-utils中的flash_eraseall等工具,就是以這些ioctl爲基礎而實現的工具,實現一些關於Flash的操做。好比,mtd 工具中 flash_eraseall中: 學習

if (ioctl(fd, MEMGETINFO, &meminfo) != 0) 
{
   fprintf(stderr, "%s: %s: unable to get MTD device info\n",exe_name, mtd_device);
   return 1;
}
MEMGETINFO是Linux MTD中的drivers/mtd/mtdchar.c中的ioctl命令,使用mtd字符設備須要加載mtdchar內核模塊。該代碼解釋了上面的第一個現象。

/dev/mtdblockN設備

/dev/mtdblockN,是Flash驅動中用add_mtd_partitions()添加MTD設備分區,而生成的對應的塊設備。MTD塊設備驅動程序可讓flash器件假裝成塊設備,實際上它經過把整塊的erase block放到ram裏面進行訪問,而後再更新到flash,用戶能夠在這個塊設備上建立一般的文件系統。 spa

而對於MTD塊設備,MTD設備層是不提供ioctl的實現方法的,也就不會有對應的MEMGETINFO命令之類,所以不能使用nandwrite,flash_eraseall,flash_erase等工具去對/dev/mtdblockN去進行操做,不然就會出現上面的現象一,同時也解釋了現象3——用mtd2擦除分區後,在用mtdblock2進行umount就會形成混亂。 code

mtd塊設備的大小能夠經過proc文件系統進行查看: 接口

~ $ cat /proc/partitions
major minor  #blocks  name

  31     0        512 mtdblock0
  31     1       1024 mtdblock1
  31     2       5632 mtdblock2
  31     3       9216 mtdblock3
 254     0   30760960 mmcblk0    
 254     1   30756864 mmcblk0p1
~ $
後面的兩個是SD塊設備的分區大小。每一個block的大小是1KB。

MTD設備分區和總結

經過proc文件系統查看mtd設備的分區狀況: 內存

~ $ cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00080000 00020000 "boot"
mtd1: 00100000 00020000 "kernel"
mtd2: 00580000 00020000 "roofs70"
mtd3: 00900000 00020000 "app"
~ $
能夠發現,實際上mtdN和mtdblockN描述的是同一個MTD分區,對應同一個硬件分區,二者的大小是同樣的,只不過是MTD設備層提供給上層的視圖不同,給上層提供了字符和塊設備兩種操做視圖——爲了上層使用的便利和須要,好比mount命令的需求,你只能掛載塊設備(有文件系統),而不能對字符設備進行掛載,不然會出現上面的現象2:無效參數。

這裏對於mtd和mtdblock設備的使用場景進行簡單總結: get

  1. mtd-utils工具只能應用與/dev/mtdN的MTD字符設備
  2. mount、umount命令只對/dev/mtdblockN的MTD塊設備有效
  3. /dev/mtdN和/dev/mtdblockN是同一個MTD設備的同一個分區(N同樣)
相關文章
相關標籤/搜索