How to use MTDJFFs2(中文)
原文:http://www.enseirb.fr/~kadionik/embedded/uclinux/mtd/howto_mtd.html
(中文没有版权,英文参考原文版权)
=======================================
HOW TO USE MTD/JFFS2 UNDER µClinux
(translated by Liang Alei)
Patrice KADIONIK, Professor Assistant at the ENSEIRB School of Electrical Engineering, Telecommunication, and Computer Science
[email protected]
http://www.enseirb.fr/~kadionik
1. MOTIVATIONS
本文将详细描述:怎样在µClinux 中step-by-step地构建一个MTD/JFFS2。
I'm currently teaching embedded system programming and propose to my students practical exercices on. In every
我目前在大学讲授“嵌入式系统编程”,并指导学生“µClinux on Motorola M5407C3 ColFire boards”的实验。一般在每个嵌入式系统中都存在有FLASH memory。通常可以用来存放配置参数(in a raw binary format)。而现在在embedded Linux中,我们可以在FLASH中放置一个文件系统,并在embedded Linux OS启动之后将其mount。这里采用的技术是MTD (Memory Technology Device),MTD将隐藏有关“物理(physical) FLASH”的编程细节(如:读/写/擦除扇区),并在MTD之上放置JFFS(2) 文件系统(Journalling Flash File System)----一种被Linux和µClinux支持的文件系统。JFFS2很robust,即在意外掉电(power failure)之后,再启动(reboot)之时不需要fsck检查。
JFFS JFFS2
MTD
FLASH, RAM
另外一种使用FLASH memory的情况(或用途)是:将Linux kernel放在FLASH中,由bootloader在启动时将Linux kernel解压缩至RAM中,然后转移至RAM引导kernel。(在此我们不将深入讨论该问题)
强烈推荐:在阅读本文这个HOWTO之前,读--再读--多读以下文档:
· The Memory Technology Device (MTD) Subsystem for Linux site. The Linux MTD, JFFS HOWTO.
· JFFS2: The Journalling Flash File System, version 2. What is JFFS2?
· A paper from David Woodhouse on JFFS2
· The David Woodhouse's presentation on JFFS2. He explains how works the Garbage Collector with JFFS2
· The www.embeddedlinuxworks.com site. JFFS- A practical guide. The list of FLASH memories supporting the MTD technology.
· Using Flash Memory with µClinux by Greg Ungerer.
· Find your Root File System with MTD by Phil Wilshire.
· CFI presentation from AMD site
I will also thank here Massimo Calo who helped me through his threads posted to the µClinux news server and his mails on MTD/JFFS.
2. MTD/JFFS/JFFS2 OVERVIEW
下面的内容摘录自我之前阅读的一篇文档(from the www.embeddedlinuxworks.com site, an article from Vipin Malik)。
" 2000年, Axis Communications AB (www.axis.com),发布了第一版的 JFFS文件系统,也是开源的(Open Sourced)。这是一个完全为嵌入式Linux系统设计的文件系统, JFFS直接设计在FLASH设备之上,能判断获知可擦除扇区的边界,以及FLASH的大小。
MTD可以看作是原始的FLASH芯片的“翻译层(translation layer)”,也正是由于MTD的存在,使得JFFS在Linux中能快速发展。基于MTD这个硬件抽象层(HAL),JFFS几乎可以被mount在任何可随机访问的设备上(如: RAM, FLASH(各种厂家的))-----只要MTD支持这些设备。
如果遇到新设备且驱动程序不存在,则找一个现存的驱动程序(做模板),然后修改其中的有关“read/write/erase”之函数,之后就可以将JFFS mount到“新设备”上了(关键是你根本不需要知道JFFS是怎么工作的)。换句话说,将JFFS文件系统与设备相关的MTD (Memory Technology Device)(包含了很多“raw FLASH chip”之Linux驱动程序)相结合,你就得到了一个完整的解决方案----即由MTD向JFFS文件系统层提供一个抽象的设备层。
在这种方式下,JFFS不关心任何特定的存储(memory)技术。任何支持随机访问的设备(甚至象NAND FLASH这样的伪随机设备)都可以与MTD接口,从而在之上实现JFFS。在设计方面,JFFS(以及JFFS2)在文件系统层中保证一个“meta-data”(或文件系统的“格式”可靠性--- "formatting" reliability),这意味只要你的 write()系统调用返回了,则可以保证数据一定是“记录”下来的 。换句话说,如果在write()命令的执行期间突然掉电了,而此时数据还没有完全写入FLASH芯片,则芯片内记录的数据要么是older数据、要么是 newer数据,或者是两者的混合,但关键是你的文件不会因此而“坏(corrupted)”了。
最初的JFFS是设计成 "append only"类型的文件系统,即“好”数据重来不会被“覆盖”( overwritten)(如:对一个已打开的文件先做rewind()操作,然后 fwrite(),没用!),新的数据总是被添加在上次“文件系统”(而不是文件)写操作的位置之后。与块数据同时被写入的“meta”数据将保证块数据在“逻辑”上已被写入文件的正确位置。当重启动(或mount)之时,整个文件系统将被扫描,零散的数据块被重新排列,以使得在读取文件之时,最新被“标记(stamped)”数据块----即那些在逻辑上覆盖了“older数据块”----被读出。而“older数据”则被标记为“回收(garbage collection)-----在适当的时候将被删除。这种“ append-only结构”的优点是“natural wear leveling on the FLASH”(译注:减少FLASH的擦除次数)。有关JFFS的“掉电可靠性(Power Down Reliability)”,我已经做一些扩展并提交了fixes(已包含在最新版本的 CVS之中),我观察的效果是500多次掉电实验大约10次失败。另外,系统中还存在一些bug,使得JFFS会随机地丢掉一些文件(甚至是静态文件)!我将 NOT推荐在产品中使用该文件系统(至少是当前版本)。
问:解决方案?答: JFFS2。
JFFS2是JFFS技术的第二版,它基于JFFS的设计思想,但是由Redhat (www.redhat.com)实现的。它采用了一种不同的方法实现“可靠性”,所有的 "erase sector"被独立管理,且可以“乱序(out-of-order)”寻址,因而当创建新文件或覆盖老文件之时,可以统一地申请一块“已擦除扇区(erase sector)”。为了保证“掉电可靠性”,在被确认已被成功写入FLASH之前(通过CRC和版本标签),文件的任何部分不会被真正覆盖。之后,老的数据块被标记为“回收”,则待到其所有的邻居(同一个扇区内的)也有相似的标记之时,该扇区被擦除。
好消息,JFFS2还支持压缩。文件数据在被写入时,通过zlib(可调整mod's)压缩;数据在被读出之时在线(on the fly)解压缩;所以事实上你无法感知你的数据是否被压缩了。因而现在你可以采用ASCII文件格式(而不是binary文件)来做日志(log)或配置(config)文件,当然二进制文件也会被压缩的。如果你的文件很“松散(sparse)”(如:其中有很多空格),呵呵,不用担心空间会浪费了。但缺点是,如果你将已经压缩过的数据写入时,系统仍将花费大量时间试图再压缩它。而此时你又无法动态关闭压缩功能。目前有些计划正在试图实现相关功能(即使是基于目录级别,对单个目录实现压缩的开关选项或属性)。
3. STEP 1: ENABLING MTD/JFFS2 UNDER µClinux
我的M5407C3 Motorola板子上,有一个16 bit FLASH内存(AMD Am29PL160C),内存映射空间是$7FE00000~$7FFFFFFF。
首先,你要认真、仔细地阅读有关你所使用的FLASH芯片的“数据手册”,查看它的扇区地址表:
我的FLASH芯片有11个扇区(大小不等)。在第一个256KB空间(SA0~SA3)中包含“dBUG Motorola monitor”代码,其余空间供用户使用(SA4~SA10,每扇区256 KB)。当然你也可以擦除“dBUG monitor”而使用整个地址空间(dBUG monitor代码可以通过BDM线缆重新安装)。我选择的方案是定义两个“MTD分区(partition)”:
· dBUG分区:$7FE00000~$7FE3FFFF (256 Kbyte size)。(我不想将monitor去除。。。)
· user分区:$7FE40000~$7FFFFFFF (1792 Kbyte size)。
如果你擦除“dBUG monitor”,则拥有一个大的user分区:
· user分区:$7FE00000~$7FFFFFFF (2 Mbyte size).
注意:(参考µClinux文档)如果你使用的是JFFS(2),每个MTD分区至少包含6个连续扇区(原因:garbage collection)。
首先,配置µClinux之时,打开“MTD/JFFS2”:
% cd uClinux-dist
% make xconfig
看一下我的有关MTD的选项:
% grep MTD linux-2.4.x/.config
# Memory Technology Devices (MTD)
CONFIG_MTD=y
CONFIG_MTD_DEBUG=y
CONFIG_MTD_DEBUG_VERBOSE=3
CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_JEDECPROBE=y
CONFIG_MTD_GEN_PROBE=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_START=0x7fe00000
CONFIG_MTD_PHYSMAP_LEN=0x200000
CONFIG_MTD_PHYSMAP_BUSWIDTH=2
其中,你已经打开CONFIG_MTD_PHYSMAP(参考uClinux-dist/linux-2.4.x/drivers/mtd/maps/physmap.c),这意味着基于一个MTD分区,你可以访问整个FLASH空间了。
为了定义多个MTD分区,我又创建了一个特殊的physmap.c文件(m5407c3.c,uClinux-dist/linux-2.4.x/drivers/mtd/maps/目录)。
之后,打开JFFS2(µClinux内核配置):
· File systems menu: JFFS2 support, JFFS2 debugging verbosity 2.
选择MTD/JFFS2工具(userland area):
· Flash Tools menu: mtd-utils with erase, mkfs.jff2.
· BusyBox menu: BusyBox with dd, mount, mount: loop devices, umount.
创建自己的MTD之physmap文件
如果你需要多个MTD分区,你可以修改uClinux-dist/linux-2.4.x/drivers/mtd/maps/physmap.c 文件(参考:Phil Wildshire's document 之解释)。
我选择在µClinux distribution中创建自己的文件(在uClinux-dist/linux-2.4.x/drivers/mtd/maps/目录下又很多参考例子,我以m5272c3.c为例,这是一个专用于M5272C3 Motorola 开发板的)。
我的m5407c3.c 文件
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/config.h>
#define WINDOW_ADDR 0x7fe00000
#define WINDOW_SIZE 0x200000
#define BUSWIDTH 2
static struct mtd_info *mymtd;
__u8 m5407c3_read8(struct map_info *map, unsigned long ofs)
{
return __raw_readb(map->map_priv_1 + ofs);
}
__u16 m5407c3_read16(struct map_info *map, unsigned long ofs)
{
return __raw_readw(map->map_priv_1 + ofs);
}
__u32 m5407c3_read32(struct map_info *map, unsigned long ofs)
{
return __raw_readl(map->map_priv_1 + ofs);
}
void m5407c3_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
memcpy_fromio(to, map->map_priv_1 + from, len);
}
void m5407c3_write8(struct map_info *map, __u8 d, unsigned long adr)
{
__raw_writeb(d, map->map_priv_1 + adr);
mb();
}
void m5407c3_write16(struct map_info *map, __u16 d, unsigned long adr)
{
__raw_writew(d, map->map_priv_1 + adr);
mb();
}
void m5407c3_write32(struct map_info *map, __u32 d, unsigned long adr)
{
__raw_writel(d, map->map_priv_1 + adr);
mb();
}
void m5407c3_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
memcpy_toio(map->map_priv_1 + to, from, len);
}
struct map_info m5407c3_map = {
name: "MCF5407C3 flash device",
size: WINDOW_SIZE,
buswidth: BUSWIDTH,
read8: m5407c3_read8,
read16: m5407c3_read16,
read32: m5407c3_read32,
copy_from: m5407c3_copy_from,
write8: m5407c3_write8,
write16: m5407c3_write16,
write32: m5407c3_write32,
copy_to: m5407c3_copy_to
};
/*
* MTD 'PARTITIONING' STUFF
*/
static struct mtd_partition m5407c3_partitions[] = {
{
name: "dBUG (256K)",
size: 0x40000,
offset: 0x0
},
{
name: "user (1792K)",
size: 0x1c0000,
offset: 0x40000
}
};
int __init init_m5407c3(void)
{
printk(KERN_NOTICE "m5407c3 flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR);
m5407c3_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
if (!m5407c3_map.map_priv_1) {
printk("Failed to ioremap\n");
return -EIO;
}
mymtd = do_map_probe("cfi_probe", &m5407c3_map);
if (mymtd) {
mymtd->module = THIS_MODULE;
mymtd->erasesize = 0x40000;
return add_mtd_partitions(mymtd, m5407c3_partitions,
sizeof(m5407c3_partitions) /
sizeof(struct mtd_partition));
}
iounmap((void *)m5407c3_map.map_priv_1);
return -ENXIO;
}
static void __exit cleanup_m5407c3(void)
{
if (mymtd) {
del_mtd_partitions(mymtd);
map_destroy(mymtd);
}
if (m5407c3_map.map_priv_1) {
iounmap((void *)m5407c3_map.map_priv_1);
m5407c3_map.map_priv_1 = 0;
}
}
module_init(init_m5407c3);
module_exit(cleanup_m5407c3);
最重要的是在mtd_partition m5407c3_partitions[]结构中,我定义了两个MTD分区。(其它内容我都是通过“替换”来修改的,即基于vi执行sed命令 :-))。
问:怎样将我的文件集成到&micro;Clinux distribution之中?我的做法是:
1. 在uClinux-dist/linux-2.4.x/drivers/mtd/maps/Config.in 文件中,添加下面行:
if [ "$CONFIG_M5407C3" ]; then dep_tristate ' CFI Flash device mapped on Motorola M5407C3' CONFIG_MTD_M5407C3 $CONFIG_MTD_CFI fi
2. 在uClinux-dist/linux-2.4.x/drivers/mtd/maps/Makefile 文件中添加:
obj-$(CONFIG_MTD_M5407C3) += m5407c3.o
于是,再次执行make xconfig,你将看到:
% cd uClinux-dist
% make xconfig
现在,我没有采用CONFIG_MTD_PHYSMAP默认选项:
# Memory Technology Devices (MTD)
CONFIG_MTD=y
CONFIG_MTD_DEBUG=y
CONFIG_MTD_DEBUG_VERBOSE=3
CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_JEDECPROBE=y
CONFIG_MTD_GEN_PROBE=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_M5407C3=y
3. STEP 2: MODIFYING THE &micro;Clinux KERNEL
3.1. Adding files from the Linux kernel distribution(添加文件)
你可以从某个地方(如:here )下载“Linux kernel version 2.4.19”,然后将linux-2.4.19/fs/jffs2/之中的pushpull.c, zlib.c, zlib.h文件拷贝到uClinux-dist/linux-2.4.x/fs/jffs2/目录下。
3.2. Modifying files from the &micro;Clinux kernel distribution(修改文件)
将这些文件中的BLKMEM_MAJOR值从“31”修改为“30”:
· uClinux-dist/linux-2.4.x/drivers/block/blkmem.c (line 41).
· uClinux-dist/linux-2.4.x/include/linux/major.h (line 66).
目的是避免造成MTD and BLKMEM之间“major”号的冲突。
3.3. Modifying files from the &micro;Clinux M5407C3 BSP port
在文件uClinux-dist/vendors/Motorola/M5407C3/Makefile 之中添加以下内容:
DEVICES = \
tty,c,5,0 console,c,5,1 cua0,c,5,64 cua1,c,5,65 \
mtd0,c,90,0 mtd1,c,90,2 mtd2,c,90,4 mtd3,c,90,6 \
mtd4,c,90,8 mtd5,c,90,10 mtd6,c,90,12 mtd7,c,90,14 \
mtdblock0,b,31,0 mtdblock1,b,31,1 mtdblock2,b,31,2 mtdblock3,b,31,3 \
mtdblock4,b,31,4 mtdblock5,b,31,5 mtdblock6,b,31,6 mtdblock7,b,31,7 \
mem,c,1,1 kmem,c,1,2 null,c,1,3 \
. . .
目的是在目标设备的uClinux目录结构之/dev目录下创建MTD and JFFS2所需要的设备文件。
4. STEP3: COMPILING(编译)
开始编译整个&micro;Clinux distribution:
% cd uClinux-dist
% make dep
% make
4. STEP4: TESTING(测试)
最后,通过网络下载&micro;Clinux的“image”文件至M5407C3板,并启动&micro;Clinux内核:
Hard Reset
DRAM Size: 32M
Copyright 1995-2001 Motorola, Inc. All Rights Reserved.
ColdFire MCF5407 EVS Firmware v2e.1a.1b (Build 18 on Apr 20 2001 11:57:55)
Enter 'help' for help.
dBUG> dn (下载)
Eth Mac Addr is 00:00:00:00:00:01
Downloading Image 'image.bin' from 192.168.4.1
Read 1891552 bytes (3695 blocks)
dBUG> go 20000 (启动)
启动显示:
Linux version 2.4.19-uc1 ([email protected]) (gcc version 2.95.3
uClinux/COLDFIRE(m5407)
COLDFIRE port done by Greg Ungerer, [email protected]
Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne
. . .
Starting kswapd
kmem_create: Forcing size word alignment - file lock cache
JFFS2 version 2.1. (C) 2001 Red Hat, Inc., designed by Axis Communications AB.
ColdFire internal UART serial driver version 1.00
ttyS0 at 0x100001c0 (irq = 73) is a builtin ColdFire UART
ttyS1 at 0x10000200 (irq = 74) is a builtin ColdFire UART
kmem_create: Forcing size word alignment - blkdev_requests
ne.c:v1.10 9/23/94 Donald Becker ([email protected])
Last modified Nov 1, 2000 by Paul Gortmaker
NE*000 ethercard probe at 0x40000300: 00 00 00 00 00 01
eth0: NE2000 found at 0x40000300, using IRQ 27.
SLIP: version 0.8.4-NET3.019-NEWTTY (dynamic channels, max=256).
CSLIP: code copyright 1989 Regents of the University of California.
Blkmem copyright 1998,1999 D. Jeff Dionne
Blkmem copyright 1998 Kenneth Albanowski
Blkmem 1 disk images:
0: 107FA4-2013A3 (RO)
RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
PPP generic driver version 2.4.2
m5407c3 flash device: 200000 at 7fe00000
Amd/Fujitsu Extended Query Table v1.0 at 0x0040
number of CFI chips: 1
Creating 2 MTD partitions on "MCF5407C3 flash device":
0x00000000-0x00040000 : "dBUG (256K)"
mtd: partition "dBUG (256K)" doesn't end on an erase block -- force read-only
mtd: Giving out device 0 to dBUG (256K)
0x00040000-0x00200000 : "user (1792K)"
mtd: Giving out device 1 to user (1792K)
init_mtdchar: allocated major number 90.
init_mtdblock: allocated major number 31.
NET4: Linux TCP/IP 1.0 for NET4.0
IP Protocols: ICMP, UDP, TCP
. . .
Command: dhcpcd -p -a eth0 &
Command: cat /etc/motd
. . .
For further information check:
http://www.uclinux.org/
Execution Finished, Exiting
Sash command shell (version 1.1.1)
看到了?JFFS2和MTD都打开了,FLASH内存也被“CFI探测”发现了,2个 MTD分区也被创建了(/dev/mtd0和/dev/mtd1)。
查看一下MTD的分区列表:
/> cd /proc
/proc> cat mtd
dev: size erasesize name
mtd0: 00040000 00038000 "dBUG (256K)"
mtd1: 001c0000 00040000 "user (1792K)"
尝试着在MTD的user分区(/dev/mtd1)上创建一个JFFS2 image:
/proc> cd /tmp
/var/tmp> mkdir fs
/var/tmp> mkdir jffs2
/var/tmp> mkdir jffs2/bin
/var/tmp> cd jffs2
/var/tmp/jffs2> vi file1
/var/tmp/jffs2> cat file1
coucou
/var/tmp/jffs2> cd ..
/var/tmp> mkfs.jffs2 -d jffs2 -o jffs2.img
/var/tmp> erase /dev/mtd1
/var/tmp> cp jffs2.img /dev/mtd1
MTD_open
MTD_write
MTD_close
“Mount”JFFS2分区:
/var/tmp> mount -t jffs2 /dev/mtdblock1 /mnt
mtdblock_open
ok
/var/tmp> cd /mnt
/mnt> ls
bin
file1
toto
/mnt> cd /proc
/proc> cat mounts
rootfs / rootfs rw 0 0
/dev/root / romfs ro 0 0
/proc /proc proc rw 0 0
/dev/ram1 /var ext2 rw 0 0
/dev/mtdblock1 /mnt jffs2 rw 0 0
查看一下所有相关的设备文件(/dev/目录):
/proc> ls -l /dev
. . .
crw------- 1 0 0 90, 0 Jan 01 1970 mtd0
crw------- 1 0 0 90, 2 Jan 01 1970 mtd1
crw------- 1 0 0 90, 6 Jan 01 1970 mtd3
crw------- 1 0 0 90, 8 Jan 01 1970 mtd4
crw------- 1 0 0 90, 10 Jan 01 1970 mtd5
crw------- 1 0 0 90, 12 Jan 01 1970 mtd6
crw------- 1 0 0 90, 14 Jan 01 1970 mtd7
brw------- 1 0 0 31, 0 Jan 01 1970 mtdblock0
brw------- 1 0 0 31, 1 Jan 01 1970 mtdblock1
brw------- 1 0 0 31, 2 Jan 01 1970 mtdblock2
brw------- 1 0 0 31, 3 Jan 01 1970 mtdblock3
brw------- 1 0 0 31, 4 Jan 01 1970 mtdblock4
brw------- 1 0 0 31, 5 Jan 01 1970 mtdblock5
brw------- 1 0 0 31, 6 Jan 01 1970 mtdblock6
brw------- 1 0 0 31, 7 Jan 01 1970 mtdblock7
. . .
最后,你也可以“umount”JFFS2分区:
/proc> umount /mnt
mtdblock_release
ok
就是这样了。
5. CONCLUSION(结论)
本文中,我描述了在&micro;Clinux 中怎样使用MTD/JFFS2 的方法(step by step),并在M5407C3板上通过测试:
相关的测试条件是:
· Linux kernel version 2.4.19.
· &micro;Clinux version 20020927.
· m68k-elf-tools version 20020410.
另外,我使用的PC是Dell laptop (Inspiron 8200, P IV at 1,7 GHz) under RedHat 8.0.
没有人是完美的,如果你发现了“不正确的”内容,请与 me 联系。 liangalei,你好,这篇文章全是你自己翻译的吗?好强啊!我正郁闷大篇英文呢!谢谢!^_^
刚看了一点,有点小问题想问一下:
“有关JFFS的“掉电可靠性(Power Down Reliability)”,我已经做一些扩展并提交了fixes(已包含在最新版本的 CVS之中),我观察的效果是500多次掉电实验大约10次失败。”是不是不大对啊?
原文:
Power Down Reliability of JFFS- the Reality I have done some extensive testing on the system and have submitted fixes (that are in the latest version of the CVS) that increases the power fail reliability of the JFFS file system from about 10 power fails (when I found it) to about 500+ reliable power fails.
似乎是说作者做了一些试验,提交了一个补丁,将掉电可靠性从10次提高到500次以上(反复掉电看数据是否丢失??),是这样子的吗? 另外想请教一下,wear level 是什么意思呢?(One beneficial side effect of this append-only structure is that it provides a natural wear leveling on the FLASH, regardless if the file is being written to or not (i.e. even the FLASH being used by the static portions of the file system are wear levelled). )
不好意思,我不懂怎么使特定的词更醒目一些。。。 你好,有关你的问题:
(1)是我翻译的;(我花了整整一个晚上,开始是学习性阅读,后来决定干脆翻译一遍吧,这样能学得更认真些)
(2)我不是JFFS专家,只是一个翻译:-)但还是尝试着回答一下你的问题。
wear level == 磨损程度,写一次“磨”一次。(加重的方法是HTML语法和[ /b])
这里是在夸append方式好,例如扩大(甚至减小)文件的大小,只要在flash最后一次写的地方加写数据,同时修改一个meta数据(相当于FAT表之类的,呵呵这里会磨损的?!);如果不用append方式,试想修改一个文件,是将修改处以及后面别的文件的数据都读出来至RAM,然后修改后,再写入(那些不需要修改的数据也经历了一次“磨损”---是吗?) meta data也是类似于append方式的。像JFFS这样的日志结构的文件系统,meta data和普通的data其实是一样处理的。 谢谢指教! liangalei兄,不好意思,因为有点别的事,把JFFS给搁下了,忘了回复。现在需要写flash,到网上一搜,才看到这篇贴子,实在是抱歉!(大骂自己一顿,忏悔中。。。) :oops:
Better late then never.多谢指点! :-) "wear level"感觉应该翻译成“负载平衡”更合适。 均衡磨损其实是比较贴切的了。Flash存储器的每个块的可擦写次数都是很有限的。
NAND的100W次左右,NOR的只有10W次左右。擦除和写入的算法不好的,可能老是在几个块上操作,这样这些Flash块很快会坏的。NAND的还好一点,因为NAND的本来就可能在出厂的时候就有坏块,需要做块映射;NOR的就不行了,坏了一个块整个FLASH都可能不能用。
负载一般针对吞吐量来说的吧。
页:
[1]