Wie kann ich die volle Kapazität einer SD-Karte unter Linux testen?


17

Ich habe eine 64-GB-SD-Karte von eBay gekauft. Es funktioniert einwandfrei, wenn ich ein Arch Linux ARM-Image darauf brenne und damit meinen Raspberry Pi starte.

Wenn ich jedoch versuche, eine einzelne ext4-Partition zu erstellen, um die gesamte Kapazität der Karte zu nutzen, treten Fehler auf. mkfs.ext4endet immer fröhlich; Die Partition kann jedoch nicht mountbearbeitet werden, es wird immer ein Fehler ausgegeben und dmesgdie Kernelmeldungen werden angezeigt Cannot find journal. Dies hat sich auf mindestens zwei Plattformen bewährt: Arch Linux ARM und Ubuntu 13.04.

Andererseits kann ich eine FAT32-Partition ohne Fehler erstellen und mounten (eine vollständige Kapazitätsprüfung wurde nicht durchgeführt).

Ich habe gehört, dass einige Bösewichte die SD-Karten-Schnittstelle ändern können, um dem Betriebssystem eine falsche Kapazität zu melden (dh die Karte hat nur 2 GB, aber sie meldet sich selbst als 64 GB), um die Karte zu einem besseren Preis zu verkaufen.

Ich weiß, dass badblockses für mich Tools gibt, mit denen ich die SD-Karte auf fehlerhafte Blöcke überprüfen kann. Können Sie badblockssolche Probleme erkennen? Wenn nicht, welche anderen Lösungen stehen mir zum Testen der Karte zur Verfügung?

Ich möchte im Idealfall wissen, ob ich betrogen wurde oder nicht. Wenn das Ergebnis zeigt, dass ich gerade einen schlechten Artikel erhalten habe, kann ich nur zum Verkäufer zurückkehren, statt eBay zu melden, dass jemand versucht hat, mich zu betrügen.

AKTUALISIEREN

Operationen und Nachrichten:

~$ 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

AKTUALISIEREN

Ich bin gelaufen, badblocks /dev/sdeaber es wird kein Fehler gemeldet. Das heißt, die verbleibenden Ursachen sind:

  • Das SD-Auto ist gut, aber aus irgendeinem Grund hat mke2fsoder mountder Kernel einen Fehler, der das Problem verursacht.

  • Ich wurde auf eine Weise betrogen badblocks, die die Niederlage nicht erkennen kann. Das ist plausibel, weil ich denke, es badblockshandelt sich nur um einen direkten Schreib-Lese-Test. Der Betrüger kann jedoch den Zugang zu ausgehenden Bereichen auf einen eingehenden Block zurückführen. In diesem Fall kann eine In-Place-Lese- / Schreibprüfung das Problem nicht erkennen.

Wenn es keine Anwendung gibt, die den richtigen Test durchführen kann, kann ich versuchen, ein einfaches C-Programm zu schreiben, um es zu testen.


Haben Sie es in einem SDXC-USB-Kartenleser versucht?
Ignacio Vazquez-Abrams

Werden gleichzeitig mit den Fehlern auch Meldungen im Systemprotokoll angezeigt?
Ignacio Vazquez-Abrams

Ich habe es sowohl mit dem nativen Raspberry Pi-Kartenleser als auch mit einem externen Kartenleser für meinen Ubuntu-Desktop versucht. Ich habe gesagt, dass dmesgKernelnachrichten angezeigt werden, und ich bin sicher, dass sie gleichzeitig mit den Fehlern angezeigt werden, da ich das vorher und nachher getan und sie verglichen habe. Ich habe nicht überprüft, syslogweil ich glaube dmesg, dass die Nachrichten angezeigt werden.
Earth Engine

Zeigt es andere Nachrichten an?
Ignacio Vazquez-Abrams

Der externe Kartenleser, den ich verwendet habe, funktioniert für meine anderen Karten, einschließlich SDXC-Karten. Dieses Problem hat jedoch einen Unterschied: Es ist eine Micro-SD-Karte mit einem SD-Adapter.
Earth Engine

Antworten:



6

Das Betrügen wurde nun durch die folgenden Schritte bestätigt:

  • Generieren Sie eine zufällige Datendatei. (4194304 = 4 × 1024 × 1024 = 4 MiB, Gesamtgröße = 40 × 4 MiB = 160 MiB)

    Befehl:

    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
    
  • Kopieren Sie die Daten auf die SD-Karte. (2038340 × 4096 = 8153600 KiB = 7962,5 MiB)

    Befehl:

    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
    
  • Lesen Sie die Daten von der SD-Karte zurück.

    Befehl:

    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
    
  • Zeigen Sie das Ergebnis

    Befehl:

    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
    
    ...
    

Was ist passiert? Wir haben eine Lücke von Nullen beobachtet. Dies ist ein Indikator dafür, dass die Zufallsdaten nicht tatsächlich auf die Karte geschrieben wurden. Aber warum kommen die Daten nachher zurück 1a81000? Offensichtlich hat die Karte einen internen Cache.

Wir können auch versuchen, das Verhalten des Caches zu untersuchen.

hexdump test.orig | grep ' 0000 0000 '

liefert kein Ergebnis, was bedeutet, dass der erzeugte Müll kein solches Muster hat. Jedoch,

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

habe 4 Treffer.

Aus diesem Grund besteht es die badblocksPrüfung. Weitere Tests können ergeben, dass die tatsächliche Kapazität 7962,5 MB oder etwas weniger als 8 GB beträgt.

Ich komme zu dem Schluss, dass dies höchstwahrscheinlich nur ein zufälliger Hardwareausfall ist, aber eher eine Art Betrug (dh Betrug). Ich würde gerne wissen, welche Maßnahmen ich ergreifen kann, um anderen Opfern zu helfen.

Update 11/05/2019

  • Die Leute fragten mich, wie ich den richtigen seekParameter herausgefunden habe 2038399. Ich habe viel mehr Erfahrung gemacht, als ich oben gezeigt habe. Grundsätzlich muss man an erster Stelle raten. Sie müssen die richtige Datengröße erraten und erraten, wo die Datenbeschädigung war. Aber Sie können immer die Halbierungsmethode verwenden , um zu helfen.

  • In dem Kommentar unten dachte ich, ich sei davon ausgegangen, dass der zweite obige Schritt (Kopieren der Daten auf SD-Karte) nur 1 Sektor kopiert. Aber ich habe diesen Fehler in meinem Experiment nicht gemacht. Stattdessen seeksollte gezeigt werden, dass im Schritt "Ergebnis anzeigen" der Versatz 1000einfach im zweiten Sektor der Daten erfolgt. Wenn das seek2038399 Sektoren ist, befindet sich die Beschädigung in dem 2038400th Sektor.


(1) Woher kommen die Nummern 2038340 und 2038399? (2) Warum verwenden Sie  bs=4194304 count=40 beim Lesen von, /dev/urandom aber   bs=4096 count=40960  beim Schreiben auf und Lesen von der SD-Karte? (Sie sind mathematisch äquivalent; jeweils 167772160 Bytes.)
Scott

1) Ich habe Bise-Technik verwendet, um diesen Versatz herauszufinden. Da das Bisec-Verfahren für die Antwort zu ausführlich ist, lege ich es ohne weitere Erklärung als offensichtlich hin. 2) Ja, die Berechnung ist gleichwertig. aber ich weiß nicht, ob ich mit der Sektorgröße der Karte übereinstimmen soll, von der ich glaube, dass sie 4096 ist.
Earth Engine

Oh, für Punkt 2) verwende ich seek, also habe ich nur 1 Sektor auf die Karte geschrieben, was den Umfang der Datenübertragung spart. Natürlich habe ich beim Experimentieren einen größeren Datenblock verwendet. Deshalb ist die generierte Datendatei 160 MB groß.
Earth Engine

Dein zweiter Kommentar ergibt keinen Sinn. Der zweite Befehl in Ihrer Antwort - der, der auf die Karte schreibt - ist sudo dd if=test.orig of=/dev/sde seek=2038399 bs=4096. Und offensichtlich hast du recht; es nutzt seek. Und, ja, technisch gesehen, funktioniert es nicht count. … (Fortsetzung)
Scott

(Fortsetzung)… Aber Sie sagen: „Ich habe nur 1 Sektor auf die Karte geschrieben, was die Datenübertragung spart.“ Das ist eindeutig falsch. Ohne countAngabe wird dddie gesamte Eingabe übertragen (dh es wird bis zu EOF oder ein Fehler übertragen). Dieser Befehl überträgt also den gesamten Inhalt von test.orig, dh 40960 Datensätze mit jeweils 4096 Bytes, für insgesamt 167772160 Bytes (wie gesagt).
Scott

3

Lesen Sie zunächst die F3- Antwort von @Radtoo. Das ist der richtige Weg.

Ich habe es irgendwie verpasst und meinen eigenen Weg versucht:

  1. 1GB Testdatei erstellen: dd if=/dev/urandom bs=1024k count=1024 of=testfile1gb

  2. Schreiben Sie Kopien dieser Datei auf die SD-Karte (64 ist die SD-Kartengröße in GB): for i in $(seq 1 64); do dd if=testfile1gb bs=1024k of=/media/sdb1/test.$i; done

  3. überprüfe md5 von Dateien (alle bis auf die letzte sollten übereinstimmen, unvollständig): md5sum testfile1gb /media/sdb1/test.*


Dies ist ein einfacher und schneller Ansatz.
Earth Engine


2

Der einfachste Weg, die volle Kapazität einer SD-Karte zu testen, besteht darin, sie mit Dateien zu füllen und dann zu überprüfen, ob die Dateien korrekt sind: diff -qr /directory/on/computer /directory/on/SD

Alternativ können Sie Programme verwenden, um Muster oder Hashketten in eine Datei zu schreiben und dann zu überprüfen, ob sie korrekt sind.

Wie @Earthy Engine betonte, ist es wichtig, die SD-Karte zu füllen und dann die Daten zu lesen, da herkömmliche Ansätze, bei denen nur ein kleiner Datenblock geschrieben und dann gelesen wird, von gefälschten SSD-Karten getäuscht werden.


2

Ich habe ein kleines Skript geschrieben, das Folgendes ausführt.

- Erstellt ein temporäres Verzeichnis auf der Ziel-USB- oder SC-Karte

-erstellt eine zufällig erzeugte 5MB Referenzdatei mit md5sum Checksumme

-kopiert die Referenzdatei zum Ziel und generiert eine MD5-Summenprüfung vom Ziel, um den Lese- / Schreiberfolg zu bestätigen

-füllt das Ziel zu 100% oder stoppt, wenn ein Prüfsummenfehler auftritt

-Nachdem das Skript auf natürliche Weise angehalten wird, werden die gemeldete Zielgröße sowie die verwendeten und freien Beträge angezeigt.

Mit diesem Skript bin ich zu dem Schluss gekommen, dass ich von einem eBay-Verkäufer verarscht wurde, der eine 8-GB-microSD für 64 GB bestanden hat

#!/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
Dies führt möglicherweise zu irreführenden Ergebnissen. Da das Betriebssystem Schreibvorgänge im Dateisystem puffert, testen Sie hauptsächlich den Arbeitsspeicher Ihres Systems und nicht die SD-Karte.
Cerin

Das Ausführen von "hdparm -W 0 / dev / disk" sollte ein gepuffertes Schreibproblem beheben.
Michael

1

Man kann eine Folge von Zahlen schreiben (jede Zeile hat 16 Bytes) und dann den Inhalt überprüfen:

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

Überprüfen Sie dann die Ausgabe von überspringen == (unter Verwendung einer kleinen Stichprobe von überspringenden Werten, bei denen es sich um eine geringere Anzahl geschriebener Datensätze handelt), z. B. überspringen = 9876 :

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

Oder machen Sie eine Stichprobe von 20 Orten mit einem Einzeiler:

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
  • Stellen Sie sicher, dass Sie auf die SD-Karte schreiben
  • Schreiben Sie in eine Datei of=tempFileOnSD, wenn Sie die Zerstörung der auf Ihrer Karte gespeicherten Daten vermeiden möchten (nur relevant, wenn es sich nicht um eine Fälschung handelt).
  • Bei einer mit 64 GB beschrifteten 8-GB-Karte beträgt die Wahrscheinlichkeit, alle 20 Tests zu bestehen, (8 GB / 64 GB) ** 20 <1e-18

1
Ich musste Ihre Antwort dreimal lesen, bevor ich verstand, was Sie sagten: "Überprüfung der Ausgabe von überspringen ==" ist nicht klar. Und wenn ich nichts vermisse, muss der Benutzer bei Ihrer Vorgehensweise die Befehle 123456789012345 ausführen und  die Ausgabe manuell überprüfen! Das ist natürlich unvernünftig. Warum nicht einfach seq -w 0 123456789012345 > /dev/yourSdHereund seq -w 0 123456789012345 | cmp - /dev/yourSdHere?
Scott

Danke für den Kommentar :) Ich habe meine Antwort bearbeitet, hoffe es ist jetzt besser!
Karpada

Außerdem ist 123456789012345 eine 15-stellige Nummer, damit jede Nummer 16 Bytes verwendet. man kann die Anzahl der 16 - Byte - Blöcke auf der SD verwenden
karpada
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.