ฉันจะทดสอบความจุเต็มของการ์ด SD ใน Linux ได้อย่างไร


17

ฉันซื้อการ์ด SD 64 GB จาก eBay มันทำงานได้ดีเมื่อฉันเผาอิมเมจ 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 ว่ามีคนพยายามโกงฉัน

UPDATE

การดำเนินงานและข้อความ:

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

UPDATE

ฉันทำงานแล้วbadblocks /dev/sdeแต่ไม่มีรายงานข้อผิดพลาด นั่นหมายถึงสาเหตุที่เหลืออยู่คือ:

  • รถ SD เป็นสิ่งที่ดี แต่ด้วยเหตุผลบางmke2fsหรือmountหรือ kernel มีข้อผิดพลาดที่ทำให้เกิดปัญหา

  • ฉันถูกโกงด้วยวิธีที่badblocksไม่สามารถตรวจจับความพ่ายแพ้ สิ่งนี้เป็นไปได้เพราะฉันคิดว่าbadblocksจะทำแบบทดสอบเขียนอ่านแทน อย่างไรก็ตามสิบแปดมงกุฎสามารถทำให้การเข้าถึงพื้นที่ขาออกเชื่อมโยงกลับไปที่บล็อกขาเข้าบางส่วน ในกรณีนี้การตรวจสอบการอ่านแบบอ่านแทนจะไม่สามารถตรวจพบปัญหาได้

หากไม่มีแอปพลิเคชันสามารถทำการทดสอบที่เหมาะสมฉันคิดว่าฉันสามารถลองเขียนโปรแกรม C อย่างง่ายเพื่อทดสอบ


คุณได้ลองใช้เครื่องอ่านการ์ด SDXC USB แล้วหรือยัง
Ignacio Vazquez-Abrams

นอกจากนี้ข้อความใด ๆ ที่ปรากฏในบันทึกของระบบในเวลาเดียวกันกับข้อผิดพลาด?
Ignacio Vazquez-Abrams

ฉันลองทั้งกับตัวอ่านการ์ด Raspberry Pi ดั้งเดิมและตัวอ่านการ์ดภายนอกสำหรับเดสก์ท็อป Ubuntu ของฉันเช่นกัน ฉันได้กล่าวว่าdmesgแสดงข้อความเคอร์เนลและฉันแน่ใจว่าจะปรากฏในเวลาเดียวกันเป็นข้อผิดพลาดเพราะฉันทำก่อนและหลังและเปรียบเทียบพวกเขา ฉันไม่ได้ตรวจสอบsyslogเพราะฉันเชื่อว่าdmesgจะแสดงข้อความ
Earth Engine

มันแสดงข้อความอื่น ๆ ?
Ignacio Vazquez-Abrams

เครื่องอ่านการ์ดภายนอกที่ฉันใช้ทำงานได้กับการ์ดอื่นของฉันรวมถึงการ์ด SDXC อย่างไรก็ตามสิ่งที่เป็นปัญหานั้นมีความแตกต่างเพียงอย่างเดียวนั่นคือการ์ด micro SD ที่มีอะแดปเตอร์ SD
Earth Engine

คำตอบ:


26

หากใครเห็นสิ่งนี้ในภายหลัง: มีคนเขียนเครื่องมือโอเพนซอร์สที่เรียกว่า "F3" เพื่อทดสอบความจุของการ์ด SD และสื่ออื่น ๆ มันสามารถพบได้บน hompage โครงการและใน Github


จริงๆแล้วมันคือการอ้างอิงในหัวข้อที่จะ SDCards ทดสอบ ...
ฟิลิปป์ Gachoud

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ภาคส่วนคือ 2,038,399 ความเสียหายอยู่ที่ภาค 2,038,400


(1) หมายเลข 2038340 และ 2038399 มาจากไหน (2) ทำไมคุณถึงใช้  bs=4194304 count=40 เมื่ออ่าน/dev/urandom แต่   bs=4096 count=40960  เมื่อเขียนและอ่านจากการ์ด SD? (พวกมันมีความเท่าเทียมกันทางคณิตศาสตร์ 167772160 bytes)
Scott

1) ฉันใช้ bisec tecnique เพื่อคำนวณค่าชดเชย เนื่องจากขั้นตอน bisec นั้นละเอียดเกินไปสำหรับคำตอบฉันเพียงแค่ทำให้พวกเขาเห็นได้อย่างชัดเจนโดยไม่ต้องทำการสำรวจเพิ่มเติม 2) ใช่การคำนวณนั้นเท่าเทียมกัน; แต่ฉันไม่รู้ว่าฉันควรจะตรงกับขนาดเซกเตอร์ของการ์ดซึ่งฉันเชื่อว่าเป็น 4096 หรือไม่
Earth Engine

โอ้สำหรับจุดที่ 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 ไบต์ (ตามที่ฉันพูด)
Scott

3

ก่อนอื่นอ่านคำตอบF3โดย @Radtoo มันเป็นวิธีที่ถูกต้อง

ฉันคิดถึงมันอย่างใดอย่างหนึ่งและลองใช้วิธีของตัวเอง:

  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 Engine

วิธีนี้ได้รับการบันทึกไว้อย่างดีที่นี่ccollins.wordpress.com/2016/01/18/testing-sd-cards-with-linux
Philippe Gachoud

2

วิธีที่ง่ายที่สุดในการทดสอบความจุเต็มของการ์ด SD คือการเติมด้วยไฟล์จากนั้นตรวจสอบว่าไฟล์ถูกต้อง: diff -qr /directory/on/computer /directory/on/SD

หรือคุณสามารถใช้โปรแกรมเพื่อเขียนรูปแบบหรือกลุ่มของแฮชไปยังไฟล์จากนั้นตรวจสอบว่าถูกต้อง

ตามที่@Earthy Engineชี้ให้เห็นจึงเป็นสิ่งสำคัญที่จะต้องเติมการ์ด SD แล้วอ่านข้อมูลตามวิธีการดั้งเดิมที่เพียงแค่เขียนบล็อกข้อมูลขนาดเล็กแล้วอ่านมันถูกหลอกโดยการ์ด SSD ปลอม


2

ฉันเขียนสคริปต์ตัวเล็ก ๆ ที่ทำสิ่งต่อไปนี้

- สร้างไดเรกทอรีชั่วคราวไปยัง USB เป้าหมายหรือการ์ด SC

- สร้างไฟล์อ้างอิง 5MB ที่สร้างแบบสุ่มด้วยการตรวจสอบ md5sum

- เลือกไฟล์อ้างอิงไปยังเป้าหมายและสร้างการตรวจสอบ md5sum จากเป้าหมายเพื่อยืนยันความสำเร็จในการอ่าน / เขียน

เติมเป้าหมายเป็นความจุ (100%) หรือหยุดเมื่อเกิดข้อผิดพลาดในการตรวจสอบ

-once สคริปต์หยุดตามธรรมชาติจะแสดงขนาดรายงานเป้าหมายปริมาณที่ใช้และฟรี

ด้วยสคริปต์นี้ฉันได้ข้อสรุปว่าฉันถูกริบโดยผู้ขายอีเบย์ที่ผ่าน microSD 8GB ขนาด 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
Cerin

กำลังดำเนินการ "hdparm -W 0 / dev / disk" ควรแก้ไขปัญหาการเขียนบัฟเฟอร์
Michael

1

หนึ่งสามารถเขียนลำดับของตัวเลข (แต่ละแถวคือ 16 ไบต์) จากนั้นตรวจสอบเนื้อหา:

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

จากนั้นตรวจสอบการข้าม == ผลลัพธ์ (โดยใช้ตัวอย่างเล็ก ๆ ของค่าข้ามที่มีจำนวนน้อยกว่าของบันทึกที่เขียน) เช่น 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หากคุณต้องการหลีกเลี่ยงการทำลายข้อมูลที่จัดเก็บในการ์ดของคุณ (เกี่ยวข้องเฉพาะในกรณีที่ไม่ใช่ของปลอม)
  • ในกรณีของการ์ด 8GB ที่ระบุว่าเป็น 64GB โอกาสที่จะผ่านการทดสอบทั้งหมด 20 ครั้งคือ (8GB / 64GB) ** 20 <1e-18

1
ฉันต้องอ่านคำตอบของคุณสามครั้งก่อนที่ฉันจะเข้าใจสิ่งที่คุณพูด:“ ตรวจสอบข้าม == ผลลัพธ์” ไม่ชัดเจน และถ้าฉันไม่มีบางสิ่งบางอย่างแนวทางของคุณต้องการให้ผู้ใช้เรียกใช้คำสั่ง 123456789012345 และ  ตรวจสอบผลลัพธ์ด้วยตนเอง ! เห็นได้ชัดว่าไม่มีเหตุผล ทำไมไม่เพียงทำseq -w 0 123456789012345 > /dev/yourSdHereและseq -w 0 123456789012345 | cmp - /dev/yourSdHere?
สกอตต์

ขอบคุณสำหรับความคิดเห็น :) ฉันได้แก้ไขคำตอบของฉันหวังว่ามันจะดีกว่าตอนนี้!
karpada

นอกจากนี้ 123456789012345 เป็นตัวเลข 15 หลักเพื่อให้แต่ละหมายเลขใช้ 16 ไบต์ หนึ่งสามารถใช้จำนวน 16byte บล็อกใน SD
karpada
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.