轉:http://kezeodsnx.pixnet.net/blog/post/34193523-mtd%E7%B0%A1%E4%BB%8B
轉:http://blog.csdn.net/liangkaiming/article/details/6235031
Character or block device?Character指的是keyboard,mouse這類device。可以向這些device讀東西出來,但不能做seek,也沒有size的觀念。而block device則可seek,也有size,一個block通常是512 bytes。
而flash的bahavior像block device,其不同點為:
1. block device的write/erash是沒有區別的
2. block device是由sector組成,而MTD則是erase block
3. hardware處理bad block,而MTD需要software
因此就有了MTD這個特別的device type。
Note: USB stick, MMC, SD, CompactFlash也稱為flash,但這些都不是flash device。他們內部有flash chip,但除了chip,還有一層模擬為block device的translation layer,且這個translation實作在硬體上,所以應視為hard drive。
MTD subsystem
MTD (Memory Techology Device)是一個subsystem,用來簡化底層的flash device (ROM/NAND/OneNAND/NOR)的driver。在MTD下,driver只需提供read/write/erase的功能,而不需知道其上是使用FTL (Flash Translation Layer),還是FFS (Flash File System)。
FTL是用來模擬Flash device為block device,因此可以在上面create filesystem。而FFS則是為flash device設計的filesystem。各有其優缺點,可見Wiki。
為了讓既有的filesystem (fat/ext/xfs...)能用在flash device上,就需要FTL這個software layer。mtdblock就是其中一種FTL。要注意的是使用FTL時,如果改了其中一個sector,就必須讀一整個eraseblock到 memory,然後erase,最後再把整個eraseblock寫回,顯然cost很高。因此通常建議使用mtdblock_ro,也可再加上 squashfs。將mtdblock mount成rw前,一定要多想一下是否值得這樣做。
mtdblock也沒有wear leveling。
Linux系统中/dev/mtd 與/dev/mtdblock 的區別
MTD(memory technology device內存技朮設備)是用於訪問memory設備(ROM、flash)的Linux的子系統。MTD的主要目的是為了使新的memory設備的驅 動更加簡單,為此它在硬件和上層之間提供了一個抽象的接口。MTD的所有源代碼在/drivers/mtd子目錄下。我將CFI接口的MTD設備分為四層 (從設備節點直到底層硬件驅動),這四層從上到下依次是:設備節點、MTD設備層、MTD原始設備層和硬件驅動層。
MTD字符驅動程序允許直接訪問flash器件,通常用來在flash上創建文件系統,也可以用來直接訪問不頻繁修改的數據。
MTD塊設備驅動程序可以讓flash器件偽裝成塊設備,實際上它通過把整塊的erase block放到ram里面進行訪問,然后再更新到flash,用戶可以在這個塊設備上創建通常的文件系統。
1. /dev/mtdN 是Linux 中的MTD架搆中,系統自己實現的mtd分區所對應的字符設備(將mtd設備分成多個區,每個區就為一個字符設備),其里面添加了一些ioctl,支持很多命令,如MEMGETINFO,MEMERASE等。
而mtd-util中的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中的:
static int mtd_ioctl(struct inode *inode, struct file *file,
u_int cmd, u_long arg)
{
。。。。。u_int cmd, u_long arg)
{
case MEMGETINFO:
info.type = mtd->type;
info.flags = mtd->flags;
info.size = mtd->size;
info.erasesize = mtd->erasesize;
info.writesize = mtd->writesize;
info.oobsize = mtd->oobsize;
/* The below fields are obsolete */
info.ecctype = -1;
info.eccsize = 0;
if (copy_to_user(argp, &info, sizeof(struct mtd_info_user)))
return -EFAULT;
break;
。。。
}
而/dev/mtdblockN,是Nand Flash驅動中,驅動用add_mtd_partitions()添加MTD設備分區(其實就是將mtd設備進行不衕的分區,當mtd設備還是一樣的,所以mtdblock分區與mtd分區肯定是對應的),而生成的對應的塊設備。根據以上內容,也就更加明白,為什么不能用nandwrite,flash_eraseall,flash_erase等工具去對/dev/mtdblockN去操作了。因為/dev/mtdblock中不包含對應的ioctl,也就沒有定義對應的命令,不支持你這么操作。
2. mtd char 設備的主設備號是90,而mtd block設備的主設備號是31:
# ls /dev/mtd* -l crw-r----- 1 root root 90, 0 May 30 2007 /dev/mtd0
crw-r----- 1 root root 90, 2 May 30 2007 /dev/mtd1
crw-r----- 1 root root 90, 4 Jul 17 2009 /dev/mtd2
crw-r----- 1 root root 90, 6 May 30 2007 /dev/mtd3
crwxrwxrwx 1 root root 90, 8 May 30 2007 /dev/mtd4
crwxrwxrwx 1 root root 90, 10 May 30 2007 /dev/mtd5
crwxrwxrwx 1 root root 90, 12 May 30 2007 /dev/mtd6
crwxrwxrwx 1 root root 90, 14 May 30 2007 /dev/mtd7
crwxrwxrwx 1 root root 90, 16 May 30 2007 /dev/mtd8
crwxrwxrwx 1 root root 90, 18 May 30 2007 /dev/mtd9
# ls /dev/mtdblock* -lbrw-r----- 1 root root 31, 0 May 30 2007 /dev/mtdblock0
brw-r----- 1 root root 31, 1 May 30 2007 /dev/mtdblock1
brw-r----- 1 root root 31, 2 May 30 2007 /dev/mtdblock2
brw-r----- 1 root root 31, 3 May 30 2007 /dev/mtdblock3
brwxrwxrwx 1 root root 31, 4 May 30 2007 /dev/mtdblock4
brwxrwxrwx 1 root root 31, 5 May 30 2007 /dev/mtdblock5
brwxrwxrwx 1 root root 31, 6 May 30 2007 /dev/mtdblock6
brwxrwxrwx 1 root root 31, 7 May 30 2007 /dev/mtdblock7
brwxrwxrwx 1 root root 31, 8 May 30 2007 /dev/mtdblock8
brwxrwxrwx 1 root root 31, 9 May 30 2007 /dev/mtdblock9
此設備號,定義在/include/linux/mtd/mtd.h中 :crw-r----- 1 root root 90, 2 May 30 2007 /dev/mtd1
crw-r----- 1 root root 90, 4 Jul 17 2009 /dev/mtd2
crw-r----- 1 root root 90, 6 May 30 2007 /dev/mtd3
crwxrwxrwx 1 root root 90, 8 May 30 2007 /dev/mtd4
crwxrwxrwx 1 root root 90, 10 May 30 2007 /dev/mtd5
crwxrwxrwx 1 root root 90, 12 May 30 2007 /dev/mtd6
crwxrwxrwx 1 root root 90, 14 May 30 2007 /dev/mtd7
crwxrwxrwx 1 root root 90, 16 May 30 2007 /dev/mtd8
crwxrwxrwx 1 root root 90, 18 May 30 2007 /dev/mtd9
# ls /dev/mtdblock* -lbrw-r----- 1 root root 31, 0 May 30 2007 /dev/mtdblock0
brw-r----- 1 root root 31, 1 May 30 2007 /dev/mtdblock1
brw-r----- 1 root root 31, 2 May 30 2007 /dev/mtdblock2
brw-r----- 1 root root 31, 3 May 30 2007 /dev/mtdblock3
brwxrwxrwx 1 root root 31, 4 May 30 2007 /dev/mtdblock4
brwxrwxrwx 1 root root 31, 5 May 30 2007 /dev/mtdblock5
brwxrwxrwx 1 root root 31, 6 May 30 2007 /dev/mtdblock6
brwxrwxrwx 1 root root 31, 7 May 30 2007 /dev/mtdblock7
brwxrwxrwx 1 root root 31, 8 May 30 2007 /dev/mtdblock8
brwxrwxrwx 1 root root 31, 9 May 30 2007 /dev/mtdblock9
#define MTD_CHAR_MAJOR 90
#define MTD_BLOCK_MAJOR 31
3. 其中,mtd的塊設備的大小,可以通過查看分區信息獲得:#define MTD_BLOCK_MAJOR 31
# cat /proc/partitions
major minor #blocks name
major minor #blocks name
31 0 1024 mtdblock0
31 1 8192 mtdblock1
31 2 204800 mtdblock2
31 3 65536 mtdblock3
31 4 225280 mtdblock4
上面中顯示的塊設備大小,是block的數目,每個block是1KB。31 1 8192 mtdblock1
31 2 204800 mtdblock2
31 3 65536 mtdblock3
31 4 225280 mtdblock4
而每個字符設備,其實就是對應著上面的每個塊設備。即/dev/mtd0對應/dev/mtdblock0,其他以此類推。換句話說,mtdblockN的一些屬性,也就是mtdN的屬性,比如大小。
4。對每個mtd字符設備的操作,比如利用nandwrite去對/dev/mtd0寫數據,實際就是操作/dev/mtdblock0。
而這些操作里面涉及到的偏移量offset,都指的是此mtd 分區內的偏移。比如向/dev/mtd1的offset為0的位置寫入數據,實際操作的是物理偏移offset=/dev/mtd0的大小=1MB=0x100000。
5.mtd的字符設備和塊設備的命名規則,可以參考下表:
Table 7-1. MTD /dev entries, corresponding MTD user modules, and relevant device major numbers
/dev entry
|
Accessible MTD user module
|
Device type
|
Major number
|
---|---|---|---|
mtdN |
char device
|
char
|
90
|
mtdrN |
char device
|
char
|
90
|
mtdblockN |
block device, read-only block device, JFFS, and JFFS2
|
block
|
31
|
nftlLN |
NFTL
|
block
|
93
|
ftlLN |
FTL
|
block
|
44
|
Table 7-2. MTD /dev entries, minor numbers, and naming schemes
/dev entry
|
Minor number range
|
Naming scheme
|
---|---|---|
mtdN |
0 to 32 per increments of 2
| N = minor / 2 |
mtdrN |
1 to 33 per increments of 2
| N = (minor - 1) / 2 |
mtdblockN |
0 to 16 per increments of 1
| N = minor |
nftlLN |
0 to 255 per sets of 16
| L = set;[2] N = minor - (set - 1) x 16; N is not appended to entry name if its value is zero. |
ftlLN |
0 to 255 per sets of 16
| Same as NFTL. |
The Linux MTD,YAFFS Howto上面這樣寫道:
Erase the mtdblock0
/>eraseall /dev/mtd0Create the mount directory and mount
/>mkdir -p /mnt/flash0
/>mount -t yaffs /dev/mtdblock0 /mnt/flash0為什么eraseall對mtd0操作?而不對mtdblock0操作?nand不是塊設備嘛,mtdblock就是塊設備呀。mtd0,mtd1與mtdblock0,mtdblock1是不是一一對應的?
沒有留言:
張貼留言