Làm cách nào tôi có thể kiểm tra toàn bộ dung lượng của thẻ SD trong Linux?


17

Tôi đã mua thẻ SD 64 GB từ eBay. Nó hoạt động tốt khi tôi ghi hình ảnh Arch Linux ARM vào nó và sử dụng nó để khởi động Raspberry Pi của tôi.

Tuy nhiên, khi tôi cố gắng tạo một phân vùng ext4 duy nhất trên đó để sử dụng tất cả dung lượng của thẻ, đã xảy ra lỗi. mkfs.ext4luôn luôn kết thúc một cách vui vẻ; tuy nhiên, phân vùng không thể được chỉnh sửa mount, luôn luôn xuất hiện lỗi và dmesghiển thị các thông báo kernel bao gồm Cannot find journal. Điều này đã được chứng minh là trường hợp trên ít nhất hai nền tảng: Arch Linux ARM và Ubuntu 13.04.

Mặt khác, tôi có thể tạo và gắn kết phân vùng FAT32 mà không gặp lỗi (kiểm tra dung lượng đầy đủ chưa được thực hiện).

Tôi nghe nói rằng một số kẻ xấu có thể thay đổi giao diện thẻ SD để báo cáo dung lượng sai cho HĐH (tức là thẻ thực sự chỉ có 2 GB nhưng nó tự báo cáo là 64 GB) để bán thẻ với giá tốt hơn.

Tôi biết rằng các công cụ như badblockstồn tại đối với tôi để kiểm tra thẻ SD xem có bị chặn không. Có thể badblocksphát hiện vấn đề như thế này? Nếu không, những giải pháp khác tồn tại cho tôi để kiểm tra thẻ?

Tôi lý tưởng muốn biết liệu tôi có bị lừa hay không; nếu kết quả cho thấy tôi vừa nhận được một mặt hàng xấu, tôi chỉ có thể quay lại với người bán, thay vì báo cáo với eBay rằng ai đó đã cố lừa dối tôi.

CẬP NHẬT

hoạt động và tin nhắn:

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

CẬP NHẬT

Tôi đã chạy badblocks /dev/sdenhưng nó báo không có lỗi. Điều đó có nghĩa là các nguyên nhân còn lại là:

  • Xe SD là tốt nhưng vì một số lý do mke2fshoặc mountnhân có lỗi gây ra vấn đề.

  • Tôi đã bị lừa theo cách badblockskhông thể phát hiện ra thất bại. Điều này là hợp lý bởi vì tôi nghĩ badblockschỉ đang thực hiện một số bài kiểm tra viết-đọc tại chỗ. Tuy nhiên, kẻ lừa đảo có thể làm cho quyền truy cập vào các khu vực bên ngoài liên kết trở lại một số khối gửi đến. Trong trường hợp này, kiểm tra ghi-đọc tại chỗ không thể phát hiện vấn đề.

Nếu không có ứng dụng nào có thể thực hiện bài kiểm tra phù hợp, tôi nghĩ tôi có thể thử viết một chương trình C đơn giản để kiểm tra nó.


Bạn đã thử nó trong một đầu đọc thẻ USB SDXC chưa?
Ignacio Vazquez-Abrams

Ngoài ra, có bất kỳ thông báo xuất hiện trong nhật ký hệ thống cùng một lúc với các lỗi không?
Ignacio Vazquez-Abrams

Tôi đã thử cả với đầu đọc thẻ Raspberry Pi nguyên bản và đầu đọc thẻ ngoài cho máy tính để bàn Ubuntu của tôi. Tôi đã nói rằng dmesghiển thị các thông báo kernel và tôi chắc chắn rằng nó xuất hiện cùng lúc với các lỗi vì tôi đã làm điều đó trước và sau và so sánh chúng. Tôi không kiểm tra syslogvì tôi tin dmesgsẽ hiển thị các tin nhắn.
Động cơ Trái đất

Nó có hiển thị bất kỳ tin nhắn khác?
Ignacio Vazquez-Abrams

Đầu đọc thẻ ngoài mà tôi đã sử dụng đang hoạt động cho các thẻ khác của mình, bao gồm thẻ SDXC. Tuy nhiên, vấn đề có một điểm khác biệt: đó là thẻ micro SD với bộ chuyển đổi SD.
Động cơ Trái đất

Câu trả lời:


26

Nếu bất cứ ai nhìn thấy điều này sau: Ai đó đã viết một công cụ nguồn mở có tên "F3" để kiểm tra dung lượng của thẻ SD và các phương tiện khác như vậy. Nó có thể được tìm thấy trên hompage dự ántrong Github .


Trên thực tế, đây là tài liệu tham khảo trong chủ đề đó để kiểm tra SDCards ...
Philippe Gachoud

6

Gian lận hiện đã được xác nhận bằng các bước sau:

  • Tạo một tệp dữ liệu ngẫu nhiên. (4194304 = 4 × 1024 × 1024 = 4 MiB, tổng kích thước = 40 × 4 MiB = 160 MiB)

    Chỉ huy:

    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
    
  • Sao chép dữ liệu vào thẻ SD. (2038340 × 4096 = 8153600 KiB = 7962,5 MiB)

    Chỉ huy:

    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
    
  • Đọc dữ liệu từ thẻ SD.

    Chỉ huy:

    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
    
  • Hiển thị kết quả

    Chỉ huy:

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

Chuyện gì đã xảy ra? Chúng tôi quan sát một khoảng trống của số không. Đây là một chỉ báo cho thấy dữ liệu ngẫu nhiên chưa thực sự được ghi vào thẻ. Nhưng tại sao dữ liệu trở lại sau 1a81000? Rõ ràng thẻ có bộ đệm trong.

Chúng tôi cũng có thể cố gắng điều tra hành vi của bộ đệm.

hexdump test.orig | grep ' 0000 0000 '

không cung cấp kết quả, có nghĩa là rác được tạo ra không có mô hình như vậy. Tuy nhiên,

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

có 4 trận đấu.

Vì vậy, đây là lý do tại sao nó vượt qua badblockskiểm tra. Các thử nghiệm tiếp theo có thể cho thấy dung lượng thực tế là 7962,5 MB, hoặc ít hơn 8 GB.

Tôi kết luận rằng điều này rất khó xảy ra chỉ là lỗi phần cứng ngẫu nhiên, nhưng nhiều khả năng là một loại gian lận (nghĩa là gian lận). Tôi muốn biết tôi có thể làm gì để giúp đỡ các nạn nhân khác.

Cập nhật 11/05/2019

  • Mọi người hỏi tôi về cách tôi tìm ra seektham số chính xác 2038399. Tôi đã làm nhiều kinh nghiệm hơn tôi đã thể hiện ở trên. Về cơ bản bạn phải đoán ở nơi đầu tiên. Bạn phải đoán kích thước phù hợp của dữ liệu và bạn phải đoán xem dữ liệu bị hỏng ở đâu. Nhưng bạn luôn có thể sử dụng phương pháp chia đôi để giúp đỡ.

  • Trong bình luận bên dưới, tôi nghĩ rằng tôi đã giả định rằng bước thứ hai ở trên (sao chép dữ liệu vào thẻ SD) chỉ sao chép 1 sector. Nhưng tôi đã không phạm sai lầm này trong thử nghiệm của mình. Thay vào đó, seekđã chỉ ra rằng trong bước "hiển thị kết quả", phần bù 1000chỉ đơn giản xảy ra trong khu vực thứ hai của dữ liệu. Nếu seeklà 2038399 lĩnh vực, tham nhũng là ở khu vực 2038400.


(1) Các số 2038340 và 2038399 đến từ đâu? (2) Tại sao bạn sử dụng  bs=4194304 count=40 khi đọc từ /dev/urandom nhưng   bs=4096 count=40960  khi viết và đọc từ thẻ SD? (Chúng tương đương về mặt toán học; 167772160 byte mỗi byte.)
Scott

1) Tôi đã sử dụng bisec tecnique để tìm ra phần bù. Vì thủ tục bisec quá dài dòng cho câu trả lời, tôi chỉ đơn giản đặt chúng như một bằng chứng rõ ràng mà không cần phải giải thích thêm. 2) Có tính toán tương đương; nhưng tôi không biết liệu tôi có nên khớp với kích thước cung của thẻ hay không, mà tôi tin là 4096.
Earth Engine

Ồ, đối với điểm 2) Tôi sử dụng seek, vì vậy tôi chỉ viết 1 sector vào thẻ, giúp tiết kiệm lượng truyền dữ liệu. Vì lý do, khi thử nghiệm tôi đã sử dụng khối dữ liệu lớn hơn, đây là lý do tại sao tệp dữ liệu được tạo là 160MiB.
Động cơ Trái đất

Nhận xét thứ hai của bạn không có ý nghĩa gì. Lệnh thứ hai trong câu trả lời của bạn - lệnh ghi vào thẻ - là sudo dd if=test.orig of=/dev/sde seek=2038399 bs=4096. Và rõ ràng là bạn đúng; nó sử dụng seek. Và, vâng, về mặt kỹ thuật, nó không sử dụng count. Tiết (Cont'd)
Scott

(Tiếp theo) Nhưng bạn nói rằng tôi chỉ viết 1 sector vào thẻ, giúp tiết kiệm lượng truyền dữ liệu. Điều đó rõ ràng là sai; không có countthông số kỹ thuật, ddchuyển toàn bộ đầu vào (nghĩa là nó chuyển tối đa EOF hoặc lỗi). Vì vậy, lệnh đó chuyển toàn bộ nội dung của test.orig, đó là 40960 bản ghi của mỗi 4096 byte, với tổng số 167772160 byte (như tôi đã nói).
Scott

3

Trước hết, hãy đọc câu trả lời F3 của @Radtoo. Đây là cách chính xác.

Tôi bằng cách nào đó đã bỏ lỡ nó, và thử theo cách của riêng tôi:

  1. tạo tập tin kiểm tra 1gb: dd if=/dev/urandom bs=1024k count=1024 of=testfile1gb

  2. ghi các bản sao của tệp đó vào sdcard (64 là kích thước sdcard tính bằng gb): for i in $(seq 1 64); do dd if=testfile1gb bs=1024k of=/media/sdb1/test.$i; done

  3. kiểm tra md5 của các tệp (tất cả trừ cuối cùng, không đầy đủ, phải khớp): md5sum testfile1gb /media/sdb1/test.*


Đây là một cách tiếp cận dễ dàng và nhanh chóng.
Động cơ Trái đất

Phương pháp này được ghi lại tốt ở đây ccollins.wordpress.com/2016/01/18/testing-sd-cards-with-linux
Philippe Gachoud

2

Cách đơn giản nhất để kiểm tra toàn bộ dung lượng của thẻ SD là lấp đầy nó bằng các tệp, sau đó xác minh các tệp là chính xác: diff -qr /directory/on/computer /directory/on/SD

Ngoài ra, bạn có thể sử dụng các chương trình để viết các mẫu hoặc chuỗi băm vào một tệp và sau đó xác minh rằng chúng là chính xác.

Như @Earthy Engine đã chỉ ra, điều quan trọng là phải điền vào thẻ SD, sau đó đọc dữ liệu, vì các phương pháp truyền thống chỉ đơn giản là viết một khối dữ liệu nhỏ, sau đó đọc nó, bị đánh lừa bởi thẻ SSD giả.


2

Tôi đã viết một kịch bản nhỏ mà làm như sau.

-Tạo thư mục tạm thời cho thẻ USB hoặc thẻ SC đích

-Tạo tệp tham chiếu được tạo ngẫu nhiên 5 MB với tổng kiểm tra md5sum

-copes tệp tham chiếu đến mục tiêu và tạo kiểm tra md5sum từ mục tiêu để xác nhận thành công đọc / ghi

- Hoàn thành mục tiêu đến công suất (100%) hoặc dừng khi xảy ra lỗi tổng kiểm tra

-theo kịch bản dừng tự nhiên, nó hiển thị kích thước mục tiêu được báo cáo, Số lượng đã sử dụng và Miễn phí.

Với kịch bản này, tôi đã kết luận rằng tôi đã bị lừa bởi một người bán ebay, người đã truyền một thẻ nhớ 8GB 8GB cho 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
Điều này có thể sẽ cho kết quả sai lệch. Do hệ thống tập tin bộ đệm của hệ điều hành ghi, bạn chủ yếu kiểm tra bộ nhớ hệ thống của bạn chứ không phải thẻ SD.
Cerin

thực thi "hdparm -W 0 / dev / đĩa" sẽ giải quyết vấn đề ghi đệm.
Michael

1

Người ta có thể viết một chuỗi số (mỗi hàng là 16 byte) và sau đó xác minh nội dung:

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

Sau đó xác minh bỏ qua == đầu ra (sử dụng một mẫu nhỏ các giá trị bỏ qua có số lượng bản ghi nhỏ hơn được viết), vd: Skip = 9876 :

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

Hoặc, tạo một mẫu gồm 20 vị trí với một lớp lót:

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
  • Đảm bảo rằng bạn đang ghi vào thẻ SD
  • Ghi vào một tệp of=tempFileOnSD, nếu bạn muốn tránh phá hủy dữ liệu được lưu trong thẻ của bạn (chỉ liên quan nếu đó không phải là giả mạo)
  • Trong trường hợp thẻ 8GB được dán nhãn là 64GB, cơ hội vượt qua tất cả 20 bài kiểm tra là (8GB / 64GB) ** 20 <1e-18

1
Tôi đã phải đọc câu trả lời của bạn ba lần trước khi tôi hiểu bạn đang nói gì: Có thể xác minh bỏ qua == đầu ra không rõ ràng. Và, trừ khi tôi thiếu một cái gì đó, cách tiếp cận của bạn yêu cầu người dùng chạy các lệnh 123456789012345 và  tự kiểm tra đầu ra! Rõ ràng đó là không hợp lý. Tại sao không chỉ làm seq -w 0 123456789012345 > /dev/yourSdHereseq -w 0 123456789012345 | cmp - /dev/yourSdHere?
Scott

Cảm ơn vì nhận xét :) Tôi đã chỉnh sửa câu trả lời của mình, hy vọng nó tốt hơn bây giờ!
karpada

Ngoài ra, 123456789012345 là một số gồm 15 chữ số để làm cho mỗi số sử dụng 16 byte. người ta có thể sử dụng số lượng khối 16byte trên SD
karpada
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.