如何检查 USB 驱动器的健康状态?
我如何知道 USB 坏了无法修复,还是可以修复?
答案1
没有办法查询 USB 记忆棒的 SMART 类参数;我不知道有任何记忆棒支持这样做,即使是通过公开的专有软件。您能做的最好的事情就是检查您是否可以使用 成功读取和写入整个设备badblocks
。
https://en.wikipedia.org/wiki/Badblocks
您想要指定其中一项写入测试,它将擦除记忆棒上的所有数据;请先进行备份。
dmesg
插入 USB 后,通过查看来找到设备;您将看到设备名称(最有可能是,例如,等)和制造商信息。确保您使用的是正确的设备!sd<letter>
sdc
sdd
如果该记忆棒使用有效的文件系统格式化,您可能必须先将其卸载(使用命令 umount
)。
示例语法,针对枚举为的 USB 记忆棒/dev/sdz
,输出进度信息,带有数据破坏性写入测试并将错误日志写入 usbstick.log
:
sudo badblocks -w -s -o usbstick.log /dev/sdz
之后,您需要重新分区并重新格式化该记忆棒(假设它通过了);此测试将清除记忆棒上的所有内容。任何故障都表明设备的内存控制器出现故障,或者它已经用尽了备用块来重新映射故障块。在这种情况下,设备的任何区域都不可信任。
答案2
通过[ubuntu] 检查 USB 闪存盘错误,我最终发现了这一点,这可能会有所帮助:
- http://oss.digirati.com.br/f3/“F3 - h2testw 的替代品”
我找到了 Fight Flash Fraud 和 SOSFakeFlash 博客,它们推荐使用软件 H2testw(参见此处或此处)来测试闪存。我下载了 H2testw,发现它有两个问题:(1)它仅适用于 Windows,(2)它不是开源的。但是,它的作者很好心地提供了一个文本文件来解释它的作用;此页面是关于我对该算法的 GPLv3 实现。
我的实现简单可靠,我不知道 F3 与 H2testw 相比究竟如何,因为我从未运行过 H2testw。我将我的实现称为 F3,即 Fight Flash Fraud 或 Fight Fake Flash 的缩写。
@pbhj 的补充:F3 在 Ubuntu 存储库中。它有两个部分,f3write 将 1GB 文件写入设备,f3read 随后尝试读取这些文件。这样可以测试容量以及写入和有效读取数据的能力。
答案3
我想这取决于故障模式。它们便宜是有原因的。
作为 USB 设备,通过 Windows 中的设备管理器观察总线或在 Linux 中通过 dmesg 的输出将告诉您该设备是否被识别为已插入。如果没有,则板上控制器或物理连接已断开。
如果设备被识别为已插入,但未被识别为磁盘控制器(我不知道这是怎么发生的,但是......)那么控制器就会被损坏。
如果它被识别为磁盘驱动器,但您无法安装它,您可能能够通过 fdisk 修复它并重写分区表,然后创建另一个文件系统。
如果你正在寻找聪明的,那么您将找不到它。拇指驱动器控制器很便宜。它们是商品存储,并不具备现代驱动器所具有的正常故障保护和智能。
答案4
许多故障要么是完全的,要么是允许一个位置支持多个位置。我编写了一个小型随机写入读取程序,该程序使用素数作为伪随机数生成器,用于模式和地址。读取在写入之后错开了足够的页面,以确保我没有在系统上测试 RAM 缓存。它尚未参数化,只是在我的系统上为具有 8G RAM 的 64G 设备设置。请随意批评、参数化,让它更智能。
这是一个强大的检查,比从下到上执行每个字节要快,但它也是一个很棒的交换生成器(几乎可以滚动出所有其他东西)。我暂时将 swapiness 设置为 1,它变慢了,但其他应用程序可以忍受。任何关于如何调整 swapout 的提示也将不胜感激:
$ sudo ksh -c'echo 1 > /proc/sys/vm/swappiness'
$ cat mysrc/test64g.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main( int argc, char **argv ){
long long int mask = 0xFFFFFFFF8L ; // 64Gb word
long long int stag = 8413257 ; // 8G / 1021
long long int inc = 1021L ; // prime < 1024
long long int w_addr = 0L ;
long long int r_addr = 0L ;
long long int w_ct = 0L ;
long long int r_ct = 0L ;
long long int w_patt = 0xFEDCBA9876543210L ;
long long int r_patt = 0xFEDCBA9876543210L ;
long long int r_buf ;
int fd, ret ;
if ( argc < 2
|| argv[1] == NULL
|| 0 > ( fd = open( argv[1], O_RDWR ))){
printf( "Fatal: Cannot open file $1 for RW.\n" );
exit( 1 );
}
while ( 1 ){
if ( (off_t)-1 == lseek( fd, w_addr & mask, SEEK_SET )){
printf( "Seek to %llX\n", w_addr & mask );
perror( "Fatal: Seek failed" );
exit( 2 );
}
if ( 8 != ( ret = write( fd, (void*)&w_patt, 8 ))){
printf( "Seek to %llX\n", w_addr & mask );
perror( "Fatal: Write failed" );
exit( 3 );
}
w_ct++ ;
w_addr += inc ;
w_patt += inc ;
if ( ( w_ct - r_ct ) < stag ){
continue ;
}
if ( (off_t)-1 == lseek( fd, r_addr & mask, SEEK_SET )){
printf( "Seek to %llX\n", r_addr & mask );
perror( "Fatal: Seek failed" );
exit( 4 );
}
if ( 8 != ( ret = read( fd, (void*)&r_buf, 8 ))){
printf( "Seek to %llX\n", w_addr & mask );
perror( "Fatal: Read failed" );
exit( 5 );
}
if ( ( ++r_ct & 0XFFFFF ) == 0 ){
printf( "Completed %lld writes, %lld reads.\n", w_ct, r_ct );
}
if ( r_buf != r_patt ){
printf( "Data miscompare on read # %lld at address %llX:\nWas: %llX\nS/B: %llX\n\n", r_ct, r_addr & mask, r_buf, r_patt );
}
r_addr += inc ;
r_patt += inc ;
}
}