原文地址:http://my.oschina.net/shelllife/blog/123482

  • 做升级方案用到了mtd-utils中的flash_eraseall和flash_cp两个工具,在进行方案验证的时候,遭遇到各种不解和疑惑,因对MTD的原理不熟悉,所以只能多次尝试,虽然最后把方案搞定了,不过觉得MTD中的mtd和mtdblock区别这块还是值得总结学习一下。这里先说明一下问题现象,然后在进行具体的区别原理解释。

MTD设备(Nor Flash)使用中的问题现象表现

  • 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.
/ $ 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
  • 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/
  • mtdblock挂载成功,但擦除后卸载失败
/ $ flash_eraseall /dev/mtd/2 <span></span> 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子目录下。
系统中的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,用户可以在这个块设备上创建通常的文件系统。

  • 而对于MTD块设备,MTD设备层是不提供ioctl的实现方法的,也就不会有对应的MEMGETINFO命令之类,因此不能使用nandwrite,flash_eraseall,flash_erase等工具去对/dev/mtdblockN去进行操作,否则就会出现上面的现象一,同时也解释了现象3——用mtd2擦除分区后,在用mtdblock2进行umount就会造成混乱。

  • mtd块设备的大小可以通过proc文件系统进行查看:

~ $ cat /proc/partitions
major minor  #blocks  name31     0        512 mtdblock031     1       1024 mtdblock131     2       5632 mtdblock231     3       9216 mtdblock3254     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设备的使用场景进行简单总结:

    • mtd-utils工具只能应用与/dev/mtdN的MTD字符设备
    • mount、umount命令只对/dev/mtdblockN的MTD块设备有效
    • /dev/mtdN和/dev/mtdblockN是同一个MTD设备的同一个分区(N一样)

mtd和mtdblock的区别相关推荐

  1. MTD应用学习:mtd和mtdblock的区别

    http://my.oschina.net/shelllife/blog/123482 http://www.cnblogs.com/hnrainll/archive/2011/06/09/20760 ...

  2. Linux系统中/dev/mtd与/dev/mtdblock的区别

    MTD(memory technology device内存技术设备)是用于访问memory设备(ROM.flash)的Linux的子系统.MTD的主要目的是为了使新的memory设备的驱动更加简单, ...

  3. linux mtd 块设备,Linux系统中/dev/mtd与/dev/mtdblock的区别,即MTD字符设备和块设备的区别...

    转:http://www.crifan.com/linux_system_in__dev__mtd_and__dev__mtdblock_distinction_character_devices_a ...

  4. /MD 与 /MT、/MTD与/MDD的区别

    VS在 属性页的 C/C++ -> Code Generation -> Runtime Library 一项中总共有四个选项 /MD 与 /MT./MTD与/MDD,它们分别有什么区别? ...

  5. MTd与MDd的区别

    C++ 程序修改或移植过程中有时出现编译错误,比如"链接错误,****__crt__**** ", 修改"项目 -> C/C++ ->代码生成 -> 运 ...

  6. VS 编译时 /MD 与 /MT、/MTD与/MDD的区别

    VS在 属性页的 C/C++ -> Code Generation -> Runtime Library 一项中总共有四个选项 /MD 与 /MT./MTD与/MDD,它们分别有什么区别? ...

  7. mtd和mtdblock之间的关系

    1. mtd-utils中的flash_eraseall和flash_cp两个工具只能操作mdtN 字符设备(将mtd设备分成多个区,每个区就为一个字符设备) 2. mount.umount命令只对/ ...

  8. linux 之 mtd and mtdblock

    MTD(memory technology device内存技术设备)是用于访问memory设备(ROM.flash)的Linux的子系统.MTD的主要目的是为了使新的memory设备的驱动更加简单. ...

  9. /MD与/MT、/MTD与/MDD的区别

    /MD 使应用程序使用运行时库的多线程并特定于DLL 的版本.定义 _MT 和 _DLL,并使编译器将库名 MSVCRT.lib 放入 .obj文件中.用此选项编译的应用程序静态链接到MSVCRT.l ...

最新文章

  1. C语言实现,设计一个将所有奇数移动到偶数之前的算法
  2. 朱俊彦团队提出GAN压缩算法:计算量减少20倍,生成效果不变,GPU、CPU统统能加速...
  3. python比java简单好学-21、PHP和python/JAVA比,哪个更好学?
  4. ccna学习指南笔记9
  5. python运算符括号_Python合集之Python运算符(四)
  6. QDoc分组事物Grouping Things
  7. One Switch 让你的 Mac 也能拥有控制中心
  8. Mac 删除不必要的 Adobe PS AI 组件
  9. dreamweaver+cs6+android,使用Dreamweaver cs6开发移动应用
  10. MySQL5.6 GTID
  11. Chrome插件安装办法【手机端】
  12. 刷屏!日本内政部向国民宣传5G的短视频:未来将是这样!
  13. python爬虫--selenium的理解以及使用(六)
  14. 图论-度序列可图性判断(Havel-Hakimi定理)
  15. IDEA配置优化,idea配置大全
  16. VMOS-Pro一款虚拟机app。
  17. 基于微信小程序的自来水收费系统设计与实现-计算机毕业设计源码+LW文档
  18. 如何编写稳定流畅的iOS移动端应用
  19. 搭载广和通5G LAN模组FM650-CN的5G工业网关已率先商用落地
  20. T型电阻网络噪声分析

热门文章

  1. 腾讯Hardcoder Android通讯框架简介
  2. 孤尽31天-day02
  3. 资源分享:嵌入式stm32项目开发 心率检测仪的设计与实现
  4. Python中的虚拟变量(dummy variables)
  5. java 虚拟机 Java内存结构 JVM垃圾回收机制算法
  6. CSP:给大家介绍下我爸爸 — Performance
  7. tplink支持Linux的无线网卡,解决tp-link usb无线网卡在ubuntu14.04下无法使用的一种方法...
  8. CUrl 创始人怒怼苹果:靠开源年赚数十亿,却把开发者当免费工具人
  9. 如何制作考试条码标签
  10. 微信小程序 给数字或文字加横线,比如原价、已完成任务