三言两语聊Kernel:flash驱动及文件系统
flash种类
flash分为nor flash和nand flash。nor flash的容量较小,但访问速度相对快;nand flash的容量较大。
访问flash的流程
用户访问flash的内容大概是要经历这些过程:
用户->vfs->具体文件系统->mtd设备(字符设备、块设备)->cfi命令字->flash。
现在的flash一般都满足cfi标准,对于不满足cfi标准的flash要使用其他的命令字.
flash空间可根据需要来灵活划分分区,比如32M的flash,做如下划分:1M(uboot),2M(kernel),4M(initrd),25M(log)。注意划分分区的大小必须要是block大小的整数倍。分区划分可以通过uboot传参的方式来做, 这样更灵活一些,当然也可以直接写死在内核里面。使用uboot传参的方式需要内核mencuonfig的支持,即打开开关:CONFIG_CMDLINE_PARTS。打开了这个开关后,内核启动时就会解析uboot传递的参数:”mtdparts=nor:1M(uboot),2M(kernel),4M(initrd),25M(log)“。在内核启动时,只是会将这些分区划分信息给存储起来, 只有真正的加载flash驱动后,即通过cfi probe具体的flash并加载其ko,然后在会读取分区划分信息并对flash空间进行划分。划分好分区后,通过/proc/mtd可以看到这些分区。同时在/dev目录下能够看到对应的mtd设备(包括块设备和字符设备),由于我们是划分的4个分区,所以可以看到mtd0、mtd1、mtd2、mtd3这四个设备。我们可以通过open这几个设备来读写对应的flash地址空间。例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
通过mtd设备赖读写flash,这种方式会绕过文件系统层,即直接通过mtd接口来读写。这种方式和dd命令读写块设备是一致的,dd命令本质上也是用的这种方式, 比如我要随即产生1M大小的内容写入到mtd3对应的地址空间中可以这样:
dd if=/dev/urandom of=/dev/mtdblock3 bs=128k count=8
dd命令一般是用来测试flash的读写速度。
上述这种方式,在内核里的执行路径大概是这样子:
1 2 3 |
|
这种方式会绕过flash的具体文件系统,而是从vfs直接到mtd层。
读写flash当然也可以使用/dev/mem的方式,/dev/mem是将外设的空间当做一块内存,然后mmap出来,这样就能直接在用户空间来操作物理地址。使用/dev/mem的示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
使用/dev/mem的这种方式,不会调用驱动接口,它是直接把flash当做一块内存来使用,所以 /dev/mem这种方式破坏性很大。
flash文件系统
flash文件系统,现在主流的有jffs2、yaffs2、ubifs。jffs2适用于nor flash,yaffs2适用于nand flash,ubifs两种flash都适用。yaffs2目前还未进入内核主线。jffs2则很早就进入了内核主线,且在业界有相对较广泛的应用。ubifs是比较新的文件系统,在性能上显著优于其余两者,不过稳定性上目前还不太好。这三种flash文件系统各自的邮件列表貌似都不太活跃,通常是好几天才能收到一封邮件:)