MTD應用學習:mtd和mtdblock的區別
http://my.oschina.net/shelllife/blog/123482
http://www.cnblogs.com/hnrainll/archive/2011/06/09/2076075.html
今天做升級方案用到了mtd-utils中的flash_eraseall和flash_cp兩個工具,在進行方案驗證的時候,遭遇到各種不解和疑惑,因對MTD的原理不熟悉,所以只能多次嘗試,雖然最后把方案搞定了,不過覺得MTD中的mtd和mtdblock區別這塊還是值得總結學習一下。這里先說明一下問題現象,然后在進行具體的區別原理解釋。
MTD設備(Nor Flash)使用中的問題現象表現
- mtd-utils工具對mtd和mtdblock分區設備的區別處理
1/ $ flash_eraseall /dev/mtdblock/22flash_eraseall: /dev/mtdblock/2: unable to get MTD device info3/ $ flash_eraseall /dev/mtdblock/24flash_eraseall: /dev/mtdblock/2: unable to get MTD device info5/ $ flash_eraseall /dev/mtd/26Erasing 128 Kibyte @ 8e0000 -- 98 % complete.7/ $ls1/ $ flashcp rootfs_version /dev/mtdblock22This doesn't seem to be a valid MTD flash device!3/ $ flashcp rootfs_version /dev/mtdblock/24This doesn't seem to be a valid MTD flash device!5/ $ flashcp rootfs_version /dev/mtd26/ $ls - mtd和mtdblock分區設備mount時的區別
1/ $mount-t jffs2 /dev/mtd/2 qqzm/2mount: Mounting /dev/mtd/2 on qqzm/ failed: Invalid argument3/ $mount-t jffs2 /dev/mtd2 qqzm/4mount: Mounting /dev/mtd2 on qqzm/ failed: Invalid argument5/ $mount-t jffs2 /dev/mtdblock/2 qqzm/6/ $ls - mtdblock掛載成功,單擦除后卸載失敗
01/ $ flash_eraseall /dev/mtd/2 <span></span> Erasing 128 Kibyte @ 8e0000 -- 98 % complete.02/qqzm $mount03/dev/root on /typejffs2 (rw,noatime)04proc on /proctypeproc (rw,nodiratime)05sysfs on /systypesysfs (rw)06devfs on /devtypedevfs (rw)07devpts on /dev/ptstypedevpts (rw)08/dev/mmcblk0p1 on /mnt/sdtypevfat (rw,nodiratime,fmask=0022,dmask=0022,codepage=cp437,iocharset=iso8859-1)09/dev/mtdblock/2 on /qqzmtypejffs2 (rw,noatime)10none on /qqzm/www/cgi-bin/tmptyperamfs (rw)11/qqzm $cd..12/ $umount/qqzm13umount: Couldn'tumount/qqzm: Inappropriate ioctlfordevice14/ $umount/dev/mtdblock/215umount: Couldn'tumount/dev/mtdblock/2: Inappropriate ioctlfordevice16/ $
通過上面的不斷嘗試和錯誤反饋,我把方案基本驗證通過了,只是對其中的原理不清楚:
- 為什么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子目錄下。
系統中的MTD設備文件
01~ $ ls /dev/mtd* -l02crw-rw---- 1 root root 90, 0 Jan 1 00:00 /dev/mtd003crw-rw---- 1 root root 90, 1 Jan 1 00:00 /dev/mtd0ro04crw-rw---- 1 root root 90, 2 Jan 1 00:00 /dev/mtd105crw-rw---- 1 root root 90, 3 Jan 1 00:00 /dev/mtd1ro06crw-rw---- 1 root root 90, 4 Jan 1 00:00 /dev/mtd207crw-rw---- 1 root root 90, 5 Jan 1 00:00 /dev/mtd2ro08crw-rw---- 1 root root 90, 6 Jan 1 00:00 /dev/mtd309crw-rw---- 1 root root 90, 7 Jan 1 00:00 /dev/mtd3ro10brw-rw---- 1 root root 31, 0 Jan 1 00:00 /dev/mtdblock011brw-rw---- 1 root root 31, 1 Jan 1 00:00 /dev/mtdblock112brw-rw---- 1 root root 31, 2 Jan 1 00:00 /dev/mtdblock213brw-rw---- 1 root root 31, 3 Jan 1 00:00 /dev/mtdblock31415/dev/mtd:16crw-rw-rw- 1 root root 90, 0 Jan 1 00:00 017cr--r--r-- 1 root root 90, 1 Jan 1 00:00 0ro18crw-rw-rw- 1 root root 90, 2 Jan 1 00:00 119cr--r--r-- 1 root root 90, 3 Jan 1 00:00 1ro20crw-rw-rw- 1 root root 90, 4 Jan 1 00:00 221cr--r--r-- 1 root root 90, 5 Jan 1 00:00 2ro22crw-rw-rw- 1 root root 90, 6 Jan 1 00:00 323cr--r--r-- 1 root root 90, 7 Jan 1 00:00 3ro2425/dev/mtdblock:26brw------- 1 root root 31, 0 Jan 1 00:00 027brw------- 1 root root 31, 1 Jan 1 00:00 128brw------- 1 root root 31, 2 Jan 1 00:00 229brw------- 1 root root 31, 3 Jan 1 00:00 330~ $可以看到有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中:
1if (ioctl(fd, MEMGETINFO, &meminfo) != 0)2{3 fprintf(stderr, "%s: %s: unable to get MTD device info\n",exe_name, mtd_device);4 return 1;5}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,用戶可以在這個塊設備上創建通常的文件系統。
而對于MTD塊設備,MTD設備層是不提供ioctl的實現方法的,也就不會有對應的MEMGETINFO命令之類,因此不能使用nandwrite,flash_eraseall,flash_erase等工具去對/dev/mtdblockN去進行操作,否則就會出現上面的現象一,同時也解釋了現象3——用mtd2擦除分區后,在用mtdblock2進行umount就會造成混亂。
mtd塊設備的大小可以通過proc文件系統進行查看:
01~ $ cat /proc/partitions02major minor #blocks name0304 31 0 512 mtdblock005 31 1 1024 mtdblock106 31 2 5632 mtdblock207 31 3 9216 mtdblock308 254 0 30760960 mmcblk0 09 254 1 30756864 mmcblk0p110~ $后面的兩個是SD塊設備的分區大小。每個block的大小是1KB。
MTD設備分區和總結
通過proc文件系統查看mtd設備的分區情況:
1~ $ cat /proc/mtd2dev: size erasesize name3mtd0: 00080000 00020000 "boot"4mtd1: 00100000 00020000 "kernel"5mtd2: 00580000 00020000 "roofs70"6mtd3: 00900000 00020000 "app"7~ $可以發現,實際上mtdN和mtdblockN描述的是同一個MTD分區,對應同一個硬件分區,兩者的大小是一樣的,只不過是MTD設備層提供給上層的視圖不一樣,給上層提供了字符和塊設備兩種操作視圖——為了上層使用的便利和需要,比如mount命令的需求,你只能掛載塊設備(有文件系統),而不能對字符設備進行掛載,否則會出現上面的現象2:無效參數。
這里對于mtd和mtdblock設備的使用場景進行簡單總結:
- mtd-utils工具只能應用與/dev/mtdN的MTD字符設備
- mount、umount命令只對/dev/mtdblockN的MTD塊設備有效
- /dev/mtdN和/dev/mtdblockN是同一個MTD設備的同一個分區(N一樣)
