打印

WINDOWS写U盘的速度究竟有多慢,谁能给个解释?!

[复制链接]
4725|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
db200|  楼主 | 2007-10-21 18:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
问题背景:在程序中读写U盘的事做过很多次了,和读写硬盘一样,没有遇到什么特别的问题,所以没有在意。而这次,是要操作U盘里的一个大文件,比如600M,打开这个文件之后,我要每隔1M字节写1个扇区(512字节),结果发现每写1个扇区的时间是120ms,也就是说写入速度是5K字节/S,而我采用大数据块方式写这个U盘时的速度至少是1M字节/S。我想一定是我的操作有问题,但我没想到问题竟是这么复杂。
(1)我换了其它U盘,现象一样,排除了U盘的问题。
(2)我的U盘是2G,FAT16,每簇32K字节。我的操作系统是WIN2000。
(3)以下的测试这样来做:连续写100次,每次512字节(共51K字节),每写1次之后就将文件指针向后移动1M字节。耗时12s。
(3)尝试改变creatfile打开文件的方式,选择 无缓冲、为连续读写优化、为随机读写优化、独占方式打开,以上这些方式组合,某些情况下,程序本身可以快速返回,但是程序返回后U盘的灯一直在闪,估计是操作系统在后台写,实际花的时间和原来一样长。
(4)测试写100个扇区,但扇区中间无间隔,是连续的,速度很快,总耗时约250ms。
(5)仍然是间隔1M字节,但不是写,而是读100次,速度很块,耗时约100ms。
(6)仍然是间隔1M字节写100次,但每次写的不是512字节,而是1K或更多,结果发现:每次写的只要在128K字节以内,时间是差不多的。也就是说写1个扇区和写256个扇区花费相同的时间。
(7)难道是因为WINDOWS的缓冲机制的问题?尝试采用文件内存映射方式,先将所有的修改提交到内存映射文件中,最后1次刷新到U盘文件,结果时间差不多。
(8)尝试在WINDOWS下直接磁盘扇区读写方式,直接写物理扇区,测试的结果和前面相同。
(9)难道说每次要操作系统写1扇区时,它都会缓存或者写U盘128K字节?否则为什么写512字节和写128K字节时间是一样的呢?能否这样来测试:1次提交一个大数据块,但是操作系统要把它写到分散的扇区中,这样操作系统不会傻到每写1个分散的扇区还去缓存一大堆数据了吧?
    实验这样做:我采用直接物理扇区读写方式,通过直接修改FAT中的文件簇链,创建了1个10M的文件,这个文件很特别,它在U盘上的位置非常不连续,共占据320个32K字节的簇、而相临的2簇之间在物理上相隔32个簇(1M字节)。然后我创建1个和文件一样大的数据块,一次写到文件,结果是:耗时395S,约120ms/簇,和前面的速度一样。
(10)众所周知,写U盘的1个扇区,不可能花费120ms的时间,我用单片机做的读写SD卡的东西,同样写零散的扇区,也只需要2ms。WINDOWS写U盘时究竟干了些什么?!各位大哥大姐,能否给个说得通的解释??

相关帖子

来自 2楼
平常人| | 2007-10-21 20:47 | 只看该作者

有缓冲机制的原因,主要是FLASH特性的原因

以现在常用的NAND Flash为例,它的最小擦除单位是128K或256K,这个最小擦除单位称为Block,当你要修改一个Block的一部分时(如1K的内容),需要进行以下操作:
1)找到要修改部分在这个Block中的位置,并确定该修改部分之前与之后的大小,如之前50K、之后77K
2)找到一个空的(已擦除的)Block
3)拷贝前50K到新的Block,随后写入要修改的1K内容,最后拷贝剩余的77K
4)将新的Block映射到原Block所对应的逻辑地址
5)擦除旧的Block

可以看出LZ的每次写操作虽然不满一个Block,但因为最小擦除单位的缘故,实际的NAND操作还是要执行写一个Block的内容,花费写一个Block的时间。而相应的读操作却不必涉及整个Block,所以花费时间也较少。

LZ的问题出在试图随机地对NAND进行操作,但NAND恰恰因为Block擦除的特点,它适合于连续地大数据量的写操作,而不适合进行这种随机写操作。

当然如果操作系统有足够大的缓冲,上述效应可以有所缓解,但总的操作时间却没有变,除非你反复地对不同的相邻区域进行随机操作。

使用特权

评论回复
板凳
McuPlayer| | 2007-10-21 18:49 | 只看该作者

有缓冲机制的原因,也有FLASH特性的原因

如果你非要测U盘的写速度,建议你用DeviceIOControl,这个比较真实。
我曾经用USB1.1的U盘实测,大约每秒700K字节,也说得过去了。
NAND的flash的最小擦除片,不是一扇区,是很多扇区,这是为什么要缓冲的缘故。

使用特权

评论回复
地板
db200|  楼主 | 2007-10-21 21:40 | 只看该作者

谢谢2位的回复。

谢谢2位的回复。我基本上明白了,简单地说,虽然我只写1扇区,但实际上要擦除128K字节的块,并重写128K字节。所以写1扇区的时间和写128K字节一样。
我的程序中其实并非要写有用的数据,而是要把这些零散的扇区清0。现在这方法的速度实在太慢。有什么快速的办法么?
我尝试用DeviceIoControl格式化磁盘,格式化软盘正常,但格式化U盘时失败,这两者有什么区别么?
在WINDOWS下有没有办法直接erase“擦除”U盘的扇区或块?或者能不能直接格式化指定的块?

使用特权

评论回复
5
平常人| | 2007-10-21 22:00 | 只看该作者

没有做过这样的操作,随便说两句

没有做过这样的操作,随便说两句,根据LZ的描述你应该是对U盘物理设备进行的操作,因为你已经跳过了文件系统可以直接操作物理扇区了,而格式化是文件系统的概念,所以你无法进行格式化操作。

不妨试试对U盘所在的卷进行操作,这样所有操作是经过文件系统的。

我没有实际做过这种操作,不太清楚具体如何做,也不知道我的理解对不对。

使用特权

评论回复
6
McuPlayer| | 2007-10-22 11:21 | 只看该作者

如果懒得用DeviceIOControl

也可以打开U盘的Handle然后,用WriteFile和ReadFile操作,速度也差不多可以达到写700K每秒的样子。
另外,调试的时候注意安全,我曾经在调试的时候误写硬盘的MBR,整了一上午才搞好。

使用特权

评论回复
7
pheavecn| | 2007-11-7 17:42 | 只看该作者

写坏MBR后,赶快备份数据。

操作系统暂时有FAT等的缓冲。

使用特权

评论回复
8
McuPlayer| | 2007-11-7 20:21 | 只看该作者

确实如此,不过我忘记备份了

没有备份MBR,一重新启动,说硬盘没有分区
最后是用DiskMan自动搜索,人工确认,重建分区
好几个同事的数据备份在我的电脑里啊,当时很担心啊

使用特权

评论回复
9
第二道彩虹| | 2012-5-12 15:40 | 只看该作者
个人感觉可能是你的文件深度太深。譬如说文件本身只有几M,但是你的文件下面是错综复杂的深度包含,那么写U盘的速度会很慢。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

75

帖子

0

粉丝