今天做公升級方案用到了mtd-utils中的flash_eraseall和flash_cp兩個工具,在進行方案驗證的時候,遭遇到各種不解和疑惑,因對mtd的原理不熟悉,所以只能多次嘗試,雖然最後把方案搞定了,不過覺得mtd中的mtd和mtdblock區別這塊還是值得總結學習一下。這裡先說明一下問題現象,然後在進行具體的區別原理解釋。
mtd-utils工具對mtd和mtdblock分割槽裝置的區別處理
?
/ $ 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
mtd和mtdblock分割槽裝置mount時的區別
/ $ 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
?
mtdblock掛載成功,單擦除後解除安裝失敗
/ $ 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 /dev/mtdblock/2
/ $
?
通過上面的不斷嘗試和錯誤反饋,我把方案基本驗證通過了,只是對其中的原理不清楚:
mtd(memory technology device記憶體技術裝置)是用於訪問memory裝置(rom、flash)的linux的子系統。mtd的主要目的是為了使新的memory裝置的驅動更加簡單,為此它在硬體和上層之間提供了乙個抽象的介面,並進行了乙個層次劃分,層次從上到下大致為:裝置檔案、mtd裝置層、mtd原始裝置層、硬體驅動層。mtd的所有源**在/drivers/mtd子目錄下。?
可以看到有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 是mtd架構中實現的mtd分割槽所對應的字元裝置(將mtd裝置分成多個區,每個區就為乙個字元裝置),其裡面新增了一些ioctl,支援很多命令,如memgetinfo,memerase等。
mtd-utils中的flash_eraseall等工具,就是以這些ioctl為基礎而實現的工具,實現一些關於flash的操作。比如,mtd 工具中 flash_eraseall中:?
if (ioctl(fd, memgetinfo, &meminfo) != 0)
memgetinfo是linux mtd中的drivers/mtd/mtdchar.c中的ioctl命令,使用mtd字元裝置需要載入mtdchar核心模組。該**解釋了上面的第乙個現象。/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檔案系統進行檢視:?
~ $ 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。通過proc檔案系統檢視mtd裝置的分割槽情況:
~ $ cat /proc/mtd
dev: size erasesize name
mtd0: 00080000 00020000 "boot"
mtd1: 00100000 00020000 "kernel"
mtd2: 00580000 00020000 "roofs70"
~ $
可以發現,實際上mtdn和mtdblockn描述的是同乙個mtd分割槽,對應同乙個硬體分割槽,兩者的大小是一樣的,只不過是mtd裝置層提供給上層的檢視不一樣,給上層提供了字元和塊裝置兩種操作檢視——為了上層使用的便利和需要,比如mount命令的需求,你只能掛載塊裝置(有檔案系統),而不能對字元裝置進行掛載,否則會出現上面的現象2:無效引數。
這裡對於mtd和mtdblock裝置的使用場景進行簡單總結:
mtd-utils工具只能應用與/dev/mtdn的mtd字元裝置
mount、umount命令只對/dev/mtdblockn的mtd塊裝置有效
/dev/mtdn和/dev/mtdblockn是同乙個mtd裝置的同乙個分割槽(n一樣)
mtd和mtdblock的區別
mtdn 是字元裝置,mtdblockn 是塊裝置 通過proc檔案系統檢視mtd裝置的分割槽情況 cat proc mtd dev size erasesize name mtd0 00100000 00010000 boot mtd1 00400000 00010000 kernel mtd2 ...
mtd和mtdblock的區別
原文 總結 可以發現,實際上mtdn和mtdblockn描述的是同乙個mtd分割槽,對應同乙個硬體分割槽,兩者的大小是一樣的,只不過是mtd裝置層提供給上層的檢視不一樣,給上層提供了字元和塊裝置兩種操作檢視 為了上層使用的便利和需要,比如mount命令的需求,你只能掛載塊裝置 有檔案系統 而不能對字...
MTD和MDd導致的問題
mtd指的是使用的執行時庫為靜態庫libcrtd.lib,mdd則使用動態庫msvcrtd.dll執行時庫作為鏈結版本 靜態庫libcrtd.lib在引用它的工程裡自定義了該靜態庫需要建立的全域性變數 動態庫msvcrtd.dll已經在dll模組內部定義了全域性變數 對malloc和free函式的呼...