ฉันได้พูดคุยกับใครบางคนเมื่อวานนี้เกี่ยวกับตรรกะและ / หรือความเป็นจริงของคำตอบของฉันที่นี่ , การเข้าสู่ระบบและการรักษาข้อมูล meta-fs บนการ์ด SD ขนาดที่เหมาะสม (GB +) อาจไม่มีนัยสำคัญพอที่จะสวมใส่การ์ด ในเวลาที่เหมาะสม (ปีและปี) เรื่องตลกของการโต้แย้งดูเหมือนว่าฉันจะต้องผิดเพราะมีเรื่องราวมากมายทางออนไลน์ของผู้คนที่ใส่การ์ด SD
เนื่องจากฉันมีอุปกรณ์ที่มีการ์ด SD ในนั้นซึ่งมีระบบไฟล์ rw root ที่เหลืออยู่ในทุกวันตลอด 24 ชั่วโมงฉันจึงทดสอบสถานที่ตั้งก่อนเพื่อความพึงพอใจของฉันเอง ฉันบิดการทดสอบนี้เล็กน้อยทำซ้ำ (โดยใช้บัตรใบเดียวกันจริง ๆ ) แล้วนำเสนอที่นี่ คำถามกลางสองข้อที่ฉันมีคือ:
- เป็นวิธีที่ผมใช้ในการพยายามที่จะทำลายการ์ดที่ทำงานได้เก็บรักษาในใจก็ตั้งใจที่จะทำผลของอย่างต่อเนื่องอีกครั้งเขียนขนาดเล็กปริมาณของข้อมูล?
- วิธีการที่ฉันใช้ในการตรวจสอบการ์ดยังใช้งานได้ดีอยู่หรือไม่?
ฉันวางคำถามไว้ที่นี่แทนที่จะเป็น SO หรือ SuperUser เพราะการคัดค้านในส่วนแรกอาจจะต้องยืนยันว่าการทดสอบของฉันไม่ได้เขียนลงในการ์ดอย่างที่ฉันแน่ใจและทำอย่างนั้น ความรู้พิเศษของ linux
[อาจเป็นเพราะการ์ด SD ใช้สมาร์ทบัฟเฟอร์หรือแคชบางอย่างเช่นการเขียนซ้ำไปยังที่เดิมซ้ำ ๆ จะถูกบัฟเฟอร์ / แคชไว้ในที่ที่ไม่ต้องสวมใส่ ฉันไม่พบสิ่งบ่งชี้ใด ๆ ที่นี่ แต่ฉันกำลังถามเกี่ยวกับสิ่งนั้นใน SU]
แนวคิดที่อยู่เบื้องหลังการทดสอบคือการเขียนบล็อกเล็ก ๆ ที่เหมือนกันบนการ์ดหลายล้านครั้ง นี่เป็นสิ่งที่ดีเกินกว่าจะอ้างได้ว่าอุปกรณ์ดังกล่าวสามารถรักษาวงจรได้เท่าไร แต่การสันนิษฐานว่าการสึกหรอระดับมีประสิทธิภาพหากการ์ดมีขนาดที่เหมาะสมจำนวนการเขียนเช่นนี้นับล้านยังคงไม่สำคัญเท่าที่ควร "บล็อกเดียวกัน" ไม่ได้เป็นบล็อกทางกายภาพเดียวกัน การทำเช่นนี้ผมจำเป็นต้องมีเพื่อให้แน่ใจว่าทุกคนเขียนได้รับการล้างอย่างแท้จริงกับฮาร์ดแวร์และเหมือนกันที่เห็นได้ชัดขึ้น
สำหรับการฟลัชกับฮาร์ดแวร์ฉันอาศัยการเรียกไลบรารี POSIX fdatasync()
:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
// Compile std=gnu99
#define BLOCK 1 << 16
int main (void) {
int in = open ("/dev/urandom", O_RDONLY);
if (in < 0) {
fprintf(stderr,"open in %s", strerror(errno));
exit(0);
}
int out = open("/dev/sdb1", O_WRONLY);
if (out < 0) {
fprintf(stderr,"open out %s", strerror(errno));
exit(0);
}
fprintf(stderr,"BEGIN\n");
char buffer[BLOCK];
unsigned int count = 0;
int thousands = 0;
for (unsigned int i = 1; i !=0; i++) {
ssize_t r = read(in, buffer, BLOCK);
ssize_t w = write(out, buffer, BLOCK);
if (r != w) {
fprintf(stderr, "r %d w %d\n", r, w);
if (errno) {
fprintf(stderr,"%s\n", strerror(errno));
break;
}
}
if (fdatasync(out) != 0) {
fprintf(stderr,"Sync failed: %s\n", strerror(errno));
break;
}
count++;
if (!(count % 1000)) {
thousands++;
fprintf(stderr,"%d000...\n", thousands);
}
lseek(out, 0, SEEK_SET);
}
fprintf(stderr,"TOTAL %lu\n", count);
close(in);
close(out);
return 0;
}
ฉันใช้เวลาประมาณ 8 ชั่วโมงจนกว่าฉันจะได้สะสม+ เขียน 2 ล้านไปยังจุดเริ่มต้นของ/dev/sdb1
พาร์ทิชัน 1 ฉันสามารถใช้งานได้ง่าย/dev/sdb
(อุปกรณ์ดิบและไม่ใช่พาร์ติชัน) แต่ฉันไม่เห็นความแตกต่างที่จะเกิดขึ้น
/dev/sdb1
จากนั้นผมก็ตรวจสอบบัตรโดยพยายามที่จะสร้างและติดตั้งระบบแฟ้มบน วิธีนี้ใช้งานได้การระบุบล็อกเฉพาะที่ฉันเขียนถึงทั้งคืนเป็นไปได้ อย่างไรก็ตามมันไม่ได้หมายความว่าบางส่วนของการ์ดไม่ได้ถูกชำรุดและถูกแทนที่โดยการปรับระดับการสึกหรอ แต่สามารถเข้าถึงได้
เพื่อทดสอบฉันใช้badblocks -v -w
พาร์ติชั่น นี่คือการทดสอบการอ่าน - เขียนแบบทำลายล้างแต่ระดับการสึกหรอหรือไม่ควรเป็นตัวบ่งชี้ที่แข็งแกร่งของความเป็นไปได้ของการ์ดเนื่องจากมันจะต้องให้พื้นที่สำหรับการเขียนแต่ละม้วน กล่าวอีกนัยหนึ่งมันเท่ากับการเติมตัวอักษรอย่างสมบูรณ์จากนั้นตรวจสอบว่าทั้งหมดนั้นใช้ได้ หลายครั้งเนื่องจากฉันปล่อยให้แบดบล็อกทำงานหลายรูปแบบ
[ความคิดเห็นของ Contra Jason C ด้านล่างไม่มีอะไรผิดปกติหรือเป็นเท็จเกี่ยวกับการใช้ badblocks ด้วยวิธีนี้ แม้ว่ามันจะไม่เป็นประโยชน์สำหรับการระบุบล็อกที่ไม่ดีเนื่องจากลักษณะของการ์ด SD มันเป็นเรื่องปกติที่จะทำการทดสอบการอ่าน - เขียนแบบทำลายล้างขนาดโดยพลการโดยใช้-b
และ-c
สวิตช์ซึ่งเป็นที่การทดสอบที่แก้ไขไป (ดูคำตอบของฉันเอง ) ไม่มีเวทมนตร์หรือการแคชโดยคอนโทรลเลอร์ของการ์ดที่จะหลอกการทดสอบโดยที่ข้อมูลหลายเมกะไบต์สามารถเขียนลงในฮาร์ดแวร์และอ่านได้อย่างถูกต้องอีกครั้ง ความคิดเห็นอื่น ๆ ของเจสันดูเหมือนจะมาจากความเข้าใจผิด - IMO เป็นความตั้งใจซึ่งเป็นเหตุผลว่าทำไมฉันไม่ใส่ใจที่จะโต้แย้ง เมื่อถึงตอนนั้นฉันก็ปล่อยให้ผู้อ่านตัดสินใจว่าอะไรเหมาะสมและอะไรที่ไม่เหมาะสม]
1การ์ดนี้เป็นการ์ด Sandisk ขนาด 4 GB (ไม่มีหมายเลข "คลาส" อยู่) ซึ่งฉันใช้แทบจะไม่ โปรดจำไว้ว่านี่ไม่ใช่การเขียน 2 ล้านฉบับในสถานที่จริง เนื่องจากการสึกหรอระดับ "บล็อกแรก" จะถูกย้ายอย่างต่อเนื่องโดยผู้ควบคุมในระหว่างการทดสอบเพื่อเป็นคำรัฐระดับการสึกหรอ
/dev/sdb1
VS /dev/sdb
มันทำให้ไม่แตกต่างกันสำหรับโปรแกรมของคุณ แต่สิ่งที่ไม่สร้างความแตกต่าง (ตามที่อธิบายไว้ด้านล่าง) คือการที่รัฐของบล็อกที่ไม่ได้ใช้ในอุปกรณ์ของคุณเป็นที่รู้จักและแปลกสำหรับในการทดสอบของคุณและถ้าคุณกรอกข้อมูลอุปกรณ์ทั้งหมด (เช่น/dev/sdb
) กับข้อมูลก่อนจำนวนของการปรับระดับการสึกหรอของพื้นที่ต้องทำงานเป็นตัวแปรหลัก ดังนั้นในขณะที่อุปกรณ์กับพาร์ติชันไม่เกี่ยวข้องกับการทดสอบของคุณซึ่งส่วนใหญ่เป็นผลมาจากการทดสอบที่มีข้อบกพร่องเนื่องจากหลังจากกรอกข้อมูลด้วยอุปกรณ์อย่างถูกต้องแล้วพาร์ทิชันต่อจะไม่เป็นตัวเลือกที่ใช้ได้
badblocks
เพื่อแสดงความล้มเหลวของหน้าบนแฟลชไดรฟ์ (และอ้างว่าเป็นสิ่งที่ทำให้เข้าใจผิดมาก) สิ่งเหล่านี้ได้รับการจัดการโดยคอนโทรลเลอร์และแมปเพื่อสำรองพื้นที่เมื่อตรวจพบ เลย์เอาต์แบบฟิสิคัลของข้อมูลในไดรฟ์นั้นไม่เหมือนกับเลย์เอาต์แบบฟิสิคัลที่คุณเห็นเมื่อทำ I / O นั่นคือการปรับระดับการสึกหรอช่วยรักษาความโปร่งใส ไม่มีของที่นี่คือปรากฏให้คุณเห็นในช่วง I / O อย่างน้อยที่สุดถ้าไดรฟ์รองรับสมาร์ทคุณสามารถรับข้อมูลเล็กน้อยเกี่ยวกับความล้มเหลวและพื้นที่สงวนที่เหลืออยู่จากคอนโทรลเลอร์