如何在Linux中测试SD卡的全部容量?


17

我从eBay购买了64 GB SD卡。当我将Arch Linux ARM映像刻录到它并使用它启动我的Raspberry Pi时,它工作正常。

但是,当我尝试在其上创建单个ext4分区以使用卡的所有容量时,会发生错误。mkfs.ext4总是快乐地完成;但是,该分区无法mount编辑,总是引发错误并dmesg显示内核消息包括Cannot find journal。事实证明,至少在两个平台上是这种情况:Arch Linux ARM和Ubuntu 13.04。

另一方面,我可以创建并挂载FAT32分区而不会出现错误(尚未完成全容量检查)。

我听说有些坏家伙可以更改SD卡接口以向操作系统报告错误的容量(即,卡实际上只有2 GB,但报告为64 GB),以便以更好的价格出售卡。

我知道我可以使用类似的工具badblocks来检查SD卡中是否有坏块。可以badblocks检测到这样的问题吗?如果没有,我还有什么其他解决方案可以测试卡?

理想情况下,我想知道我是否受到欺骗;如果结果显示我刚收到坏货,我只能退回给卖家,而是向eBay报告有人试图欺骗我。

更新

操作和消息:

~$ sudo mkfs.ext4 /dev/sde1
mke2fs 1.42.5 (29-Jul-2012)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
4096000 inodes, 16383996 blocks
819199 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=4294967296
500 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks: 
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
4096000, 7962624, 11239424

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done   

~$ dmesg | tail
...
[4199.749118]...
~$ sudo mount /dev/sde1 /mnt
mount: wrong fs type, bad option, bad superblock on /dev/sde1,
   missing codepage or helper program, or other error
   In some cases useful info is found in syslog - try
   dmesg | tail  or so

~$ dmesg | tail
...
[ 4199.749118]...
[ 4460.857603] JBD2: no valid journal superblock found
[ 4460.857618] EXT4-fs (sde1): error loading journal

更新

我已经跑了,badblocks /dev/sde但是没有报错。这意味着剩下的原因是:

  • SD车很好,但是由于某种原因mke2fsmount内核有导致问题的错误。

  • 我被欺骗了badblocks,无法察觉失败。这是合理的,因为我认为badblocks这只是在进行一些原位读写测试。但是,作弊者可以使对出站区域的访问链接回到某些入站块。在这种情况下,就地写读检查无法检测到该问题。

如果没有应用程序可以进行适当的测试,我想我可以尝试编写一个简单的C程序来对其进行测试。


您是否在SDXC USB读卡器中尝试过?
伊格纳西奥·巴斯克斯

另外,是否有任何消息与错误同时出现在系统日志中?
伊格纳西奥·巴斯克斯

我既尝试了本机Raspberry Pi读卡器,也尝试了适用于我的Ubuntu桌面的外部读卡器。我已经说过了,它dmesg显示了内核消息,并且我确信它与错误同时出现,因为我之前和之后都进行了比较。我没有检查,syslog因为我相信dmesg会显示消息。
Earth Engine

它还会显示其他消息吗?
伊格纳西奥·巴斯克斯

我使用的外部读卡器可用于其他卡,包括SDXC卡。但是,有问题的是有一个区别:它是带有SD适配器的微型SD卡。
Earth Engine

Answers:



6

现在已通过以下步骤确认了作弊:

  • 生成随机数据文件。(4194304 = 4×1024×1024 = 4 MiB,总大小= 40×4 MiB = 160 MiB)

    命令:

    dd if=/dev/urandom of=test.orig bs=4194304 count=40
    40+0 records in
    40+0 records out
    167772160 bytes (168 MB) copied, 11.0518 s, 15.2 MB/s
    
  • 将数据复制到SD卡。(2038340×4096 = 8153600 KiB = 7962.5 MiB)

    命令:

    sudo dd if=test.orig of=/dev/sde seek=2038399 bs=4096
    40960+0 records in
    40960+0 records out
    167772160 bytes (168 MB) copied, 41.6087 s, 4.0 MB/s
    
  • 从SD卡读回数据。

    命令:

    sudo dd if=/dev/sde of=test.result skip=2038399 bs=4096 count=40960
    40960+0 records in
    40960+0 records out
    167772160 bytes (168 MB) copied, 14.5498 s, 11.5 MB/s
    
  • 显示结果

    命令:

    hexdump test.result | less
    ...
    0000ff0 b006 fe69 0823 a635 084a f30a c2db 3f19
    0001000 0000 0000 0000 0000 0000 0000 0000 0000
    *
    1a81000 a8a5 9f9d 6722 7f45 fbde 514c fecd 5145
    
    ...
    

发生了什么?我们观察到零的差距。这表明随机数据尚未实际写入卡中。但是为什么数据会在之后返回1a81000呢?显然,该卡具有内部缓存。

我们还可以尝试调查缓存的行为。

hexdump test.orig | grep ' 0000 0000 '

没有提供结果,这意味着生成的垃圾没有这种模式。然而,

hexdump test.result | grep ' 0000 0000 '
0001000 0000 0000 0000 0000 0000 0000 0000 0000
213b000 0000 0000 0000 0000 0000 0000 0000 0000
407b000 0000 0000 0000 0000 0000 0000 0000 0000
601b000 0000 0000 0000 0000 0000 0000 0000 0000

有4个匹配项。

因此,这就是通过badblocks检查的原因。进一步的测试可以显示实际容量为7962.5 MB,或略小于8 GB。

我得出的结论是,这不太可能仅仅是随机的硬件故障,而更有可能是一种作弊(即欺诈)。我想知道我可以采取什么行动来帮助其他受害者。

更新11/05/2019

  • 人们问我如何确定正确的seek参数是2038399。我的经验比上面显示的要多。基本上,您必须首先猜测。您必须猜测适当的数据大小,并且必须猜测数据损坏的位置。但是您始终可以使用二等分法来提供帮助。

  • 在下面的评论中,我认为我假设上述第二步(将数据复制到SD卡)仅复制1个扇区。但是我并没有在实验中犯这个错误。而是seek显示在“显示结果”步骤中,偏移1000仅发生在数据的第二个扇区中。如果seek是2038399个扇区,则腐败发生在第2038400个扇区。


(1)数字2038340和2038399从何而来?(2)为什么使用  bs=4194304 count=40 读取的时候/dev/urandom ,但   bs=4096 count=40960  写入和从SD卡读取数据时?(它们在数学上是等效的;每个167772160字节。)
斯科特,

1)我用bisec技术计算了偏移量。由于bisec程序对于答案来说太冗长,因此,我将它们简单地视为显而易见,无需进一步说明。2)是的,计算是等价的;但我不知道我是否应该匹配的卡,我相信的扇区大小是4096
地球引擎

哦,对于第2点),我确实使用seek,所以我只在卡上写入了1个扇区,从而节省了数据传输量。当然,在实验中我使用了更大的数据块时,这就是为什么生成的数据文件为160MiB的原因。
Earth Engine

您的第二条评论没有任何意义。答案中的第二个命令是写在卡上的命令sudo dd if=test.orig of=/dev/sde seek=2038399 bs=4096。显然你是对的;它使用seek。而且,是的,从技术上讲,它不使用count。…(续)
斯科特,

(续)…但是您说“我只在卡上写了1个扇区,这样可以节省数据传输量。” 这显然是错误的。如果没有count规范,则dd传输整个输入(即,传输至EOF或错误)。因此,该命令将传输的全部内容test.orig,即40960条记录,每条记录4096字节,总共167772160字节(如我所说)。
斯科特,

3

首先,阅读@Radtoo 的F3答案。这是正确的方法。

我以某种方式错过了它,并尝试了自己的方式:

  1. 创建1gb测试文件: dd if=/dev/urandom bs=1024k count=1024 of=testfile1gb

  2. 将该文件的副本写入sdcard(64为sdcard大小,以GB为单位): for i in $(seq 1 64); do dd if=testfile1gb bs=1024k of=/media/sdb1/test.$i; done

  3. 检查文件的md5(除最后一个以外,所有不完整的都应匹配): md5sum testfile1gb /media/sdb1/test.*


这是一种简便快捷的方法。
Earth


2

测试SD卡的全部容量的最简单方法是将文件填满,然后验证文件是否正确: diff -qr /directory/on/computer /directory/on/SD

或者,您可以使用程序将模式或哈希链写入文件,然后验证它们是否正确。

正如@Earthy Engine所指出的那样,填充SD卡然后读取数据非常重要,因为传统的方法只是简单地写入一小块数据,然后读取它,就被伪造的SSD卡所欺骗。


2

我写了一个小脚本,可以执行以下操作。

-为目标USB或SC卡创建一个临时目录

-使用md5sum校验和创建一个5MB随机生成的参考文件

-将参考文件复制到目标并从目标生成md5sum检查以确认读取/写入成功

-将目标填充到容量(100%)或在发生校验和错误时停止

-一旦脚本自然停止,它将显示目标报告的大小,已用和可用量。

有了这个脚本,我得出的结论是,我被一个eBay卖家抢走了,该卖家通过了8GB microSD和64GB

#!/bin/bash
#Save file as 'filltext' and remember to set the executable flag to run it
if [ -d "$1" ]; then
 if [ -d "$1/tmp" ]; then
  echo "."
 else
  mkdir $1/tmp
 fi

#Make a tmp file and fill it with 3MB of junk
 TMPTSTR=$(mktemp)      
 base64 </dev/urandom  | head -c 5000000 > $TMPTSTR

 TESTVAL=$(md5sum $TMPTSTR | awk '{ print $1 }')

 while $CHECKEDOK; do

  FL=$( tr -dc A-Za-z0-9 </dev/urandom  | head -c 5).TEST

  cp $TMPTSTR $1/tmp/$FL
  TESTTMP=$(md5sum $1/tmp/$FL | awk '{ print $1 }')
  if [ "$TESTVAL" != "$TESTTMP" ]; then   
   echo "Checksum ERROR"
   echo "Original: $TESTVAL Temp File:$TESTTMP"
   CHECKEDOK=false
   df $1 -Ph
   echo 
   echo 
   echo "Removing test files"
   rm $1/tmp -r
   rm $TMPTSTR
   df $1 -Ph
  else
   #echo -n "$FL..."
   clear
   df $1 -Ph
  fi
 done

else
 echo "Error: Directory $1 does not exists."
 echo "Usage: filltest [PATH]"
 echo
 echo "Try the PATH of a mounted USB dongle or SD card to confirm it's capacity"

fi

1
这可能会产生误导性的结果。由于操作系统会缓冲文件系统写入操作,因此您主要是在测试系统的内存,而不是SD卡。
塞林,2016年

执行“ hdparm -W 0 / dev / disk”应解决缓冲的写问题。
迈克尔

1

可以写一个数字序列(每行为16个字节),然后验证内容:

dd if=<(seq -w 0 123456789012345) of=/dev/yourSdHere

然后验证skip ==输出(使用少量的跳过值样本,这些样本的写入记录数量较少),例如skip = 9876

dd if=/dev/yourSdHere bs=16 count=1 skip=9876
000000000009876
1+0 records in
1+0 records out
16 bytes copied, ...

或者,使用一根衬管对20个位置进行采样:

seq -w 000000000000000 NumberOfWrittenRecords | shuf | head -20 | while read i; do [[ $(dd if=/dev/yourSdHere bs=16 count=1 skip=$i) == $i ]] && echo ok || echo bad; done
  • 确保您正在写入SD卡
  • of=tempFileOnSD如果要避免破坏存储卡中的数据,则写入文件(仅在不是假的情况下才相关)
  • 对于标记为64GB的8GB卡,通过所有20次测试的机会为(8GB / 64GB)** 20 <1e-18

1
在理解您的意思之前,我必须阅读三遍您的答案:“ verify skip == output”尚不清楚。并且,除非我缺少任何内容,否则您的方法要求用户运行123456789012345命令并  手动检查输出!显然,这是不合理的。为什么不只是做seq -w 0 123456789012345 > /dev/yourSdHereseq -w 0 123456789012345 | cmp - /dev/yourSdHere
斯科特,

感谢您的评论:)我已经编辑了答案,希望现在更好!
karpada

另外,123456789012345是一个15位数字,使每个数字使用16个字节。一个人可以使用SD上16字节块的数量
karpada,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.