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/2 |
2 |
flash_eraseall: /dev/mtdblock/2: unable to get MTD device info |
3 |
/ $ flash_eraseall /dev/mtdblock/2 |
4 |
flash_eraseall: /dev/mtdblock/2: unable to get MTD device info |
5 |
/ $ flash_eraseall /dev/mtd/2 |
6 |
Erasing 128 Kibyte @ 8e0000 -- 98 % complete. |
1 |
/ $ flashcp rootfs_version /dev/mtdblock2 |
2 |
This doesn't seem to be a valid MTD flash device! |
3 |
/ $ flashcp rootfs_version /dev/mtdblock/2 |
4 |
This doesn't seem to be a valid MTD flash device! |
5 |
/ $ flashcp rootfs_version /dev/mtd2 |
- mtd和mtdblock分区设备mount时的区别
1 |
/ $ mount -t jffs2 /dev/mtd/2 qqzm/ |
2 |
mount: Mounting /dev/mtd/2 on qqzm/ failed: Invalid argument |
3 |
/ $ mount -t jffs2 /dev/mtd2 qqzm/ |
4 |
mount: Mounting /dev/mtd2 on qqzm/ failed: Invalid argument |
5 |
/ $ mount -t jffs2 /dev/mtdblock/2 qqzm/ |
- mtdblock挂载成功,单擦除后卸载失败
01 |
/ $ flash_eraseall /dev/mtd/2 <span></span> Erasing 128 Kibyte @ 8e0000 -- 98 % complete. |
03 |
/dev/root on / type jffs2 (rw,noatime) |
04 |
proc on /proc type proc (rw,nodiratime) |
05 |
sysfs on /sys type sysfs (rw) |
06 |
devfs on /dev type devfs (rw) |
07 |
devpts on /dev/pts type devpts (rw) |
08 |
/dev/mmcblk0p1 on /mnt/sd type vfat (rw,nodiratime,fmask=0022,dmask=0022,codepage=cp437,iocharset=iso8859-1) |
09 |
/dev/mtdblock/2 on /qqzm type jffs2 (rw,noatime) |
10 |
none on /qqzm/www/cgi-bin/tmp type ramfs (rw) |
13 |
umount: Couldn't umount /qqzm: Inappropriate ioctl for device |
14 |
/ $ umount /dev/mtdblock/2 |
15 |
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设备文件
02 |
crw-rw---- 1 root root 90, 0 Jan 1 00:00 /dev/mtd0 |
03 |
crw-rw---- 1 root root 90, 1 Jan 1 00:00 /dev/mtd0ro |
04 |
crw-rw---- 1 root root 90, 2 Jan 1 00:00 /dev/mtd1 |
05 |
crw-rw---- 1 root root 90, 3 Jan 1 00:00 /dev/mtd1ro |
06 |
crw-rw---- 1 root root 90, 4 Jan 1 00:00 /dev/mtd2 |
07 |
crw-rw---- 1 root root 90, 5 Jan 1 00:00 /dev/mtd2ro |
08 |
crw-rw---- 1 root root 90, 6 Jan 1 00:00 /dev/mtd3 |
09 |
crw-rw---- 1 root root 90, 7 Jan 1 00:00 /dev/mtd3ro |
10 |
brw-rw---- 1 root root 31, 0 Jan 1 00:00 /dev/mtdblock0 |
11 |
brw-rw---- 1 root root 31, 1 Jan 1 00:00 /dev/mtdblock1 |
12 |
brw-rw---- 1 root root 31, 2 Jan 1 00:00 /dev/mtdblock2 |
13 |
brw-rw---- 1 root root 31, 3 Jan 1 00:00 /dev/mtdblock3 |
16 |
crw-rw-rw- 1 root root 90, 0 Jan 1 00:00 0 |
17 |
cr--r--r-- 1 root root 90, 1 Jan 1 00:00 0ro |
18 |
crw-rw-rw- 1 root root 90, 2 Jan 1 00:00 1 |
19 |
cr--r--r-- 1 root root 90, 3 Jan 1 00:00 1ro |
20 |
crw-rw-rw- 1 root root 90, 4 Jan 1 00:00 2 |
21 |
cr--r--r-- 1 root root 90, 5 Jan 1 00:00 2ro |
22 |
crw-rw-rw- 1 root root 90, 6 Jan 1 00:00 3 |
23 |
cr--r--r-- 1 root root 90, 7 Jan 1 00:00 3ro |
26 |
brw------- 1 root root 31, 0 Jan 1 00:00 0 |
27 |
brw------- 1 root root 31, 1 Jan 1 00:00 1 |
28 |
brw------- 1 root root 31, 2 Jan 1 00:00 2 |
29 |
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中:
1 |
if (ioctl(fd, MEMGETINFO, &meminfo) != 0) |
3 |
fprintf(stderr, "%s: %s: unable to get MTD device info\n",exe_name, mtd_device); |
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/partitions |
02 |
major minor #blocks name |
08 |
254 0 30760960 mmcblk0 |
09 |
254 1 30756864 mmcblk0p1 |
后面的两个是SD块设备的分区大小。每个block的大小是1KB。
MTD设备分区和总结
通过proc文件系统查看mtd设备的分区情况:
2 |
dev: size erasesize name |
3 |
mtd0: 00080000 00020000 "boot" |
4 |
mtd1: 00100000 00020000 "kernel" |
5 |
mtd2: 00580000 00020000 "roofs70" |
6 |
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应用学习札记【转】
转自:https://blog.csdn.net/lh2016rocky/article/details/70885421 今天做升级方案用到了mtd-utils中的flash_eraseall和fl ...
- mybatis学习$与#号取值区别
1,多个参数传递用map或实体封装后再传给myBatis, mybatis学习$与#号取值区别 #{} 1.加了单引号, 2.#号写是可以防止sql注入,比较安全 select * from use ...
- Linux系统中/dev/mtd与/dev/mtdblock的区别,即MTD字符设备和块设备的区别
转:http://www.crifan.com/linux_system_in__dev__mtd_and__dev__mtdblock_distinction_character_devices_a ...
- 深度学习VS机器学习——到底什么区别
转自:https://baijiahao.baidu.com/s?id=1595509949786067084&wfr=spider&for=pc 最近在听深度学习的课,老师提了一个基 ...
- Maven学习----dependencies与dependencyManagement的区别(转)
转自:http://blog.csdn.net/liutengteng130/article/details/46991829 1.DepencyManagement应用场景 当我们的项目模块很多的时 ...
- UNITY3D单词学习 speed和velocity的区别
在日常用语中,这两个词没有区别,可以通用. 而在物理学里,velocity 是一个矢量(vector quantity)表示起点与终点间直线距离的长度除以所用时间所得的量,并注明方向;而 speed ...
- java核心知识点学习----并发和并行的区别,进程和线程的区别,如何创建线程和线程的四种状态,什么是线程计时器
多线程并发就像是内功,框架都像是外功,内功不足,外功也难得精要. 1.进程和线程的区别 一个程序至少有一个进程,一个进程至少有一个线程. 用工厂来比喻就是,一个工厂可以生产不同种类的产品,操作系统就是 ...
- C语言学习_include<>与include""的区别
经常会遇到两种include引用头文件的情况,其实区别很简单,如下: 一.#include< > #include< > 引用的是编译器的类库路径里面的头文件. 假如你编译器定 ...
- Java学习之equals和==的区别
转自:http://www.cnblogs.com/zhxhdean/archive/2011/03/25/1995431.html java中的数据类型,可分为两类: 1.基本数据类型 也称原始数 ...
随机推荐
- homework做了些什么?
第一步:get_new_guid_uid_pairs_{$ymd} 参数是时间和100上的文件. 那么100上的文件是从哪里来的呢? 我们进入到100机器上,打开root权限下的cron,看到如下内容 ...
- HDU-1015(暴力)
Safecracker Problem Description === Op tech briefing, 2002/11/02 06:42 CST === "The item is loc ...
- 如何快速学习bootstrap
bootstrap中文网http://www.bootcss.com/解决了我所有使用bootstrap的问题,从0开始,下面的全部链接都是该网站的子链接.例子http://v3.bootcss.co ...
- 学习java随笔第三篇:java的基本数据类型
数据类型 一:整型 1.十进制 2.八进制 八进制数是满8进1,包含0~7的8个数字,在整数前面添加一个"0",表示是八进制数. 3.十六进制 十六进制数是满16进1,包含0~9, ...
- python基础知识二
对象 python把在程序中用到的任何东西都成为对象. 每一个东西包括数.字符串甚至函数都是对象. 使用变量时只需要给他们赋一个值.不需要声明或定义数据类型. 逻辑行与物理行 物理行是你在编写程序时所 ...
- dispatchkeyevent的调用机制
http://blog.csdn.net/look85/article/details/23740761 dispatchKeyEvent和onKeyDown关系: 当键盘按下时 首先触发dispat ...
- 设置appicon和启动图
设置appicon General – App Icon Source 设置AppIcon 图片大小 iphone 6P(@3x) 180x180 iphone 6(@2x) iphone5/5s ( ...
- GCD的一点理解
大家都知道GCD 有两种队列:一种是串行队列,一种是并发队列.什么是串行队列?串行队列就是队列中的代码块一个一个按顺序执行,每当上一个代码块执行结束后下一个代码块才会执行.打个比方,如果队列是一些首尾 ...
- cocos2d-x 2.2.0 如何在lua中注册回调函数给C++
cocos2d-x内部使用tolua进行lua绑定,但是引擎并没有提供一个通用的接口让我们可以把一个lua函数注册给C++层面的回调事件.翻看引擎的lua绑定代码,我们可以仿照引擎中的方法来做.值得吐 ...
- mahout分类
分类看起来比聚类和推荐麻烦多了 分类算法与聚类和推荐算法的不同:必须是有明确结果的,必须是有监督的,主要用于预测和检测 Mahout的优势 mahout的分类算法对资源的要求不会快于训练数据和测试数据 ...