Kiểm tra căng thẳng thẻ SD bằng linux


19

Tôi đã có một cuộc tranh luận nhỏ với ai đó ngày hôm qua về logic và / hoặc tính xác thực của câu trả lời của tôi ở đây , rằng, việc ghi nhật ký và duy trì dữ liệu meta fs trên thẻ SD có kích thước (GB +) không bao giờ đủ đáng kể để đeo thẻ trong một khoảng thời gian hợp lý (năm và năm). Ý chính của cuộc tranh luận dường như là tôi phải sai vì có quá nhiều câu chuyện trực tuyến về những người đeo thẻ SD.

Vì tôi có các thiết bị có thẻ SD trong đó có chứa các hệ thống tập tin gốc rw còn sót lại 24/7, tôi đã thử nghiệm tiền đề trước đây để tự hài lòng. Tôi đã điều chỉnh bài kiểm tra này một chút, lặp lại nó (thực tế là sử dụng cùng một thẻ) và đang trình bày nó ở đây. Hai câu hỏi trung tâm tôi có là:

  1. Là phương pháp tôi đã sử dụng để cố gắng phá hỏng thẻ có thể tồn tại được không, hãy nhớ rằng nó có ý định tái tạo hiệu ứng của việc liên tục viết lại một lượng nhỏ dữ liệu?
  2. Là phương pháp tôi đã sử dụng để xác minh thẻ vẫn còn khả thi?

Tôi đang đặt câu hỏi ở đây chứ không phải SO hay SuperUser bởi vì sự phản đối đối với phần đầu tiên có lẽ phải khẳng định rằng bài kiểm tra của tôi không thực sự ghi vào thẻ theo cách tôi chắc chắn, và khẳng định rằng sẽ cần một số kiến thức đặc biệt về linux.

[Cũng có thể là thẻ SD sử dụng một số loại bộ đệm hoặc bộ đệm thông minh, do đó việc ghi lặp lại vào cùng một vị trí sẽ được đệm / lưu vào bộ đệm ở một nơi nào đó ít bị hao mòn hơn. Tôi không tìm thấy bất kỳ dấu hiệu nào về điều này ở bất cứ đâu, nhưng tôi đang hỏi về điều đó trên SU]

Ý tưởng đằng sau bài kiểm tra là viết vào cùng một khối nhỏ trên thẻ hàng triệu lần. Điều này vượt xa mọi tuyên bố về việc có bao nhiêu chu kỳ ghi như vậy mà các thiết bị có thể duy trì, nhưng giả sử cân bằng hao mòn có hiệu quả, nếu thẻ có kích thước khá, hàng triệu lần viết như vậy vẫn không quan trọng lắm, vì "cùng một khối" sẽ không thực sự là cùng một khối vật lý. Để làm điều này, tôi cần đảm bảo rằng mọi ghi đều thực sự được chuyển sang phần cứng và đến cùng một vị trí rõ ràng .

Để xóa phần cứng, tôi đã dựa vào cuộc gọi thư viện 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;
}                                 

Tôi đã chạy nó trong 8 giờ, cho đến khi tôi tích lũy được 2 triệu + ghi vào đầu /dev/sdb1phân vùng. 1 Tôi có thể dễ dàng sử dụng /dev/sdb(thiết bị thô chứ không phải phân vùng) nhưng tôi không thể thấy điều này sẽ tạo ra sự khác biệt gì.

Sau đó tôi đã kiểm tra thẻ bằng cách cố gắng tạo và gắn hệ thống tập tin vào /dev/sdb1. Điều này đã làm việc, chỉ ra khối cụ thể mà tôi đã viết cho cả đêm là khả thi. Tuy nhiên, điều đó không có nghĩa là một số vùng của thẻ không bị hao mòn và bị dịch chuyển do cân bằng độ mòn, nhưng vẫn có thể truy cập được.

Để kiểm tra điều đó, tôi đã sử dụng badblocks -v -wtrên phân vùng. Đây là một bài kiểm tra đọc-ghi phá hủy , nhưng mặc cân bằng hay không, nó phải là một dấu hiệu mạnh mẽ về tính khả thi của thẻ vì nó vẫn phải cung cấp không gian cho mỗi lần ghi. Nói cách khác, nó hoàn toàn tương đương với việc điền đầy đủ vào thẻ, sau đó kiểm tra xem tất cả những thứ đó có ổn không. Một vài lần, vì tôi đã để badblocks hoạt động thông qua một vài mẫu.

[Ý kiến ​​của Contra Jason C bên dưới, không có gì sai hay sai khi sử dụng badblocks theo cách này. Mặc dù sẽ không hữu ích khi thực sự xác định các khối xấu do bản chất của thẻ SD, nhưng sẽ rất tốt khi thực hiện các bài kiểm tra đọc ghi phá hủy có kích thước tùy ý bằng cách sử dụng các công tắc -b-cchuyển đổi, đó là nơi kiểm tra đã được sửa đổi (xem câu trả lời của riêng tôi ). Bộ điều khiển của thẻ không có phép thuật hoặc bộ nhớ đệm nào có thể đánh lừa bài kiểm tra, theo đó một vài megabyte dữ liệu có thể được ghi vào phần cứng và đọc lại chính xác. Những bình luận khác của Jason dường như dựa trên việc đọc sai - IMO một ý định có chủ ý , đó là lý do tại sao tôi không bận tâm tranh luận. Với cái đầu đó, tôi để nó cho độc giả quyết định điều gì có ý nghĩa và điều gì không .]

1 Thẻ là thẻ Sandisk 4 GB cũ (không có số "hạng" trên đó) mà tôi hầu như không sử dụng. Một lần nữa, hãy nhớ rằng đây không phải là 2 triệu ghi vào cùng một vị trí vật lý; do cân bằng hao mòn, "khối đầu tiên" sẽ được bộ điều khiển di chuyển liên tục trong quá trình thử nghiệm, như thuật ngữ trạng thái, san bằng độ mòn.


Đây là một thử nghiệm không đáng tin cậy cho các lý do được nêu dưới đây. Ngoài ra, bạn không thể sử dụng badblocksđể hiển thị lỗi trang trên ổ đĩa flash (và cho rằng điều đó rất sai lệch). Chúng được xử lý bởi bộ điều khiển và ánh xạ tới không gian dự trữ khi được phát hiện. Bố cục vật lý của dữ liệu trên ổ đĩa không giống với bố cục vật lý mà bạn thấy khi thực hiện I / O, đó là cách cân bằng hao mòn duy trì độ trong suốt của nó. Không ai trong số này có thể nhìn thấy bạn trong I / O. Nhiều nhất, nếu ổ đĩa hỗ trợ SMART, bạn có thể nhận được một ít thông tin về lỗi và không gian dành riêng từ bộ điều khiển.
Jason C

Đối /dev/sdb1vs /dev/sdbnó làm cho không có sự khác biệt cho chương trình của bạn, nhưng những gì không tạo sự khác biệt (như mô tả dưới đây) là tình trạng khối chưa sử dụng trên thiết bị của bạn chưa được biết rõ và mất tích trong thử nghiệm của bạn, và trừ khi bạn lấp đầy toàn bộ thiết bị (ví dụ /dev/sdb) với dữ liệu đầu tiên, số lượng cân bằng hao mòn không gian phải làm việc là một biến số chính. Vì vậy, mặc dù thiết bị so với phân vùng không liên quan đến thử nghiệm của bạn, nhưng điều đó chủ yếu là hậu quả của thử nghiệm thiếu sót, vì sau khi điền đúng thiết bị với dữ liệu, mỗi phân vùng sẽ không phải là một tùy chọn khả dụng (trừ khi bạn định dạng sau).
Jason C

Tuy nhiên, một điểm khác khiến bài kiểm tra của bạn không thực tế là một trang có thể (và khá phổ biến) không thành công nhưng vẫn để lại thẻ SD 100% có thể sử dụng được sau đó. Trong trường hợp lỗi được phát hiện và che dấu bởi bộ điều khiển nhưng dữ liệu không thể đọc được, dữ liệu hệ thống tệp có thể bị hỏng khi bộ điều khiển cố gắng sao chép khối.
Jason C

Tôi nói với bạn điều gì - mô tả cho tôi bằng các thuật ngữ cụ thể một bài kiểm tra có thể lặp lại mà không đeo thẻ SD, và sau đó tôi sẽ nghiêm túc với bạn. "Yêu sách từ chính quyền" không thể chấp nhận được và những giai thoại cá nhân chỉ có thế. Argumentum ab auctorites
goldilocks

1
Tôi không biết về thẻ cụ thể đó, nhưng hầu hết trong số họ ít nhất đã chết một chút. Những kẻ này đã hack vi điều khiển trên ít nhất một nhãn hiệu thẻ SD: bunniestudios.com/blog/?p=3554 Trò chuyện hàng giờ họ làm về chủ đề này khá hay.
mikeerv

Câu trả lời:


11

Tôi nghĩ rằng việc kiểm tra căng thẳng thẻ SD nói chung có vấn đề với 2 điều:

  1. cân bằng hao mòn Không có gì đảm bảo rằng một người viết tiếp theo thực sự đang thực hiện các vị trí vật lý tương tự trên SD. Hãy nhớ rằng hầu hết các hệ thống SD tại chỗ đang tích cực thực hiện một khối như chúng ta biết và di chuyển vị trí vật lý quay lưng lại dựa trên "hao mòn" nhận thức mà mỗi vị trí đã phải chịu.

  2. công nghệ khác nhau (MLC so với SLC) Vấn đề khác mà tôi thấy với điều này là sự khác biệt về công nghệ. Các loại SSD SLC tôi mong đợi sẽ có tuổi thọ cao hơn nhiều so với loại MLC. Ngoài ra, có nhiều dung sai chặt chẽ hơn đối với MLC mà bạn không phải đối phó với SLC, hoặc ít nhất là họ khoan dung hơn nhiều khi thất bại theo cách này.

    • MLC - Tế bào đa cấp
    • SLC - Tế bào đơn cấp

Vấn đề với MLC là một ô đã cho có thể lưu trữ nhiều giá trị, các bit về cơ bản được xếp chồng lên nhau bằng điện áp, thay vì chỉ là vật lý + 5V hoặc 0V, do đó, điều này có thể dẫn đến tiềm năng tỷ lệ thất bại cao hơn nhiều so với SLC của chúng tương đương.

Tuổi thọ

Tôi tìm thấy liên kết này thảo luận một chút về thời gian phần cứng có thể kéo dài. Nó có tiêu đề: Biết SSD của bạn - SLC so với MLC .

SLC

Các ssds SLC có thể được tính toán, phần lớn, sống ở bất cứ đâu trong khoảng từ 49 đến 149 năm, theo ước tính tốt nhất. Thử nghiệm Memoright có thể xác nhận SSD 128Gb có tuổi thọ ghi bền hơn 200 năm với tốc độ ghi trung bình 100Gb mỗi ngày.

MLC

Đây là nơi thiết kế mlc thiếu. Không ai đã được phát hành cho đến nay. Không ai thực sự kiểm tra loại tuổi thọ nào được đảm bảo với mlc ngoại trừ điều đó, nó sẽ thấp hơn đáng kể. Tôi đã nhận được một số niềm tin khác nhau, trung bình có tuổi thọ từ 10 đến 1 ủng hộ thiết kế slc. Một dự đoán thận trọng là hầu hết các ước tính tuổi thọ sẽ đến trong khoảng từ 7 đến 10 năm, tùy thuộc vào sự tiến bộ của 'đại số cân bằng mặc' trong bộ điều khiển của mỗi nhà sản xuất.

So sánh

Để so sánh bằng cách viết chu kỳ viết, một slc sẽ có vòng đời 100.000 chu kỳ ghi hoàn chỉnh so với mlc có vòng đời 10.000 chu kỳ ghi. Điều này có thể tăng đáng kể tùy thuộc vào thiết kế của 'mức độ hao mòn' được sử dụng.


1
Cân bằng hao mòn WRT "Không có gì đảm bảo rằng một người viết cho người tiếp theo thực sự đang thực hiện cùng một vị trí vật lý trên SD" - đó là giả định trong câu hỏi slm! Rất rõ ràng, tôi nghĩ rằng ... Nếu không có mức độ hao mòn, tôi sẽ không bao giờ hy vọng bài kiểm tra này sẽ vượt qua vì tôi sẽ vượt quá bất kỳ mức tối đa vòng đời ghi đã nêu nào. Thử nghiệm nhằm chứng minh tính hiệu quả của việc cân bằng độ mòn , không bỏ qua nó. Việc tôi có thể viết 2 triệu lần đến cùng một vị trí rõ ràng cho thấy mức độ hao mòn đang có hiệu lực.
goldilocks

WRT # 2, chất lượng và công nghệ tất nhiên sẽ phân biệt thẻ này với thẻ khác. Quan điểm của tôi là thẻ Sandisk giá rẻ vẫn còn tồn tại lâu hơn bất kỳ ai thực sự cần nó nếu lượng dữ liệu được viết mỗi ngày tương đối nhỏ.
goldilocks

@goldilocks - OK, OK, đừng đánh tôi về điều đó. 8-), vì vậy những gì bạn đang nói là nếu tôi viết một lượng dữ liệu đủ lớn để tôi loại bỏ hiệu quả mức độ hao mòn khỏi phương trình và chạy các lỗi xấu trên nó, điều đó có đủ để cho thấy hiệu quả của việc cân bằng hao mòn không?
slm

1
@goldilocks - Có phải tôi vừa mở hộp pandora không?
slm

1
(Ví dụ: Nếu bạn sao chép một thẻ SD bằng cách viết một hình ảnh để nó và không / không thể fstrimsau đó, bạn đã hoàn toàn tàn tật động mặc san lấp mặt bằng [bạn sẽ khó ép để tìm một thẻ SD lớp người tiêu dùng với tĩnh mặc san lấp mặt bằng] bởi đánh dấu mỗi trang như được sử dụng.)
Jason C

6

Có một số vấn đề với bài kiểm tra của bạn, một số mờ, một số không. Nó cũng phụ thuộc vào mục tiêu của bạn. Hai vấn đề mờ nhạt, tinh vi là:

  • Bạn không đọc từ cùng một khu vực mà bạn đang viết, kiểm tra đọc của bạn một cách hiệu quả, sau đó, không có gì (trừ khi bộ điều khiển đã đọc sửa lỗi, trong trường hợp đó đôi khi nó có thể di chuyển trang đang đọc sang một nơi khác, nhưng điều này vẫn không không ảnh hưởng đến bài kiểm tra của bạn).
  • Bạn giả định (và có khả năng, nhưng không được bảo đảm) rằng bộ đọc / ghi vào khối xấu được bộ điều khiển phát hiện và báo cáo - bạn sẽ muốn ghi dữ liệu, đọc lại và so sánh nó để kiểm tra được bảo đảm.

Tuy nhiên, những người được cho là pedantic. Nghiêm trọng hơn là:

  • Bạn không thể sử dụng badblocksđể hiển thị cho bạn các trang bị lỗi trên bộ nhớ flash; tất cả các phát hiện lỗi và ánh xạ trang tiếp theo được thực hiện bởi bộ điều khiển và trong suốt đối với HĐH. Bạn có thể nhận được một số thông tin từ SMART nếu ổ đĩa hỗ trợ nó (Tôi biết không có thẻ SD nào hỗ trợ nó, có thể có ổ đĩa ngón tay cái cao hơn nào).
  • Việc cân bằng hao mòn, phức tạp do thử nghiệm của bạn không tính đến các lệnh TRIM trước đó, trạng thái miễn phí / được sử dụng của ổ đĩa trong quá trình kiểm tra và không gian dành riêng.

Cân bằng hao mòn: Vấn đề chính là cân bằng hao mòn là một biến số lớn trong thử nghiệm của bạn. Nó xảy ra trên bộ điều khiển (thông thường), và trong mọi trường hợp, thiết bị trực tiếp trong suốt của nó thậm chí tìm kiếm + đọc / ghi. Trong ví dụ của bạn, bạn thực sự không biết trạng thái cân bằng hao mòn (cụ thể là các lệnh TRIM có được cấp cho các khối miễn phí gần đây không?) ...

Để cân bằng hao mòn động (hiện diện trong hầu hết tất cả các thiết bị lưu trữ cấp tiêu dùng) trên thiết bị của bạn, sau đó, nó có thể ở bất kỳ trạng thái nào: Ở một thái cực, không có trang nào được đánh dấu là miễn phí và do đó, các trang duy nhất mà bộ điều khiển phải hoạt động với những cái trong không gian dành riêng (nếu có). Lưu ý rằng nếu có không gian dành riêng trên thiết bị, nó sẽ phải thất bại hoàn toàn trước khi bạn bắt đầu nhận được bảo lãnh không vào viết trang (giả sử không có các trang khác đánh dấu là còn lại miễn phí). Ở một thái cực khác, mọi trang đều được đánh dấu là miễn phí, trong trường hợp đó về mặt lý thuyết bạn phải có mọi trang trên thiết bị bị lỗi trước khi bạn bắt đầu thấy lỗi ghi.

Đối với cân bằng hao mòn tĩnh (mà SSD có xu hướng không có, thẻ SD có xu hướng không có và ổ ngón tay cái khác nhau): Thực sự không có cách nào khác, ngoài việc ghi lại nhiều lần vào mỗi trang trên thiết bị.

... Nói cách khác, có các chi tiết cân bằng hao mòn mà bạn không có cách nào biết và chắc chắn không có cách nào kiểm soát - đặc biệt là có sử dụng cân bằng hao mòn động hay không, có sử dụng cân bằng hao mòn tĩnh hay không lượng không gian dành cho thiết bị để cân bằng hao mòn (không thể nhìn thấy qua bộ điều khiển [hoặc trình điều khiển trong một số trường hợp, như DiskOnChip cũ của M-Systems]).

SLC / MLC: Đối với SLC so với MLC, điều này có tác động rất trực tiếp đến các giới hạn mà bạn mong đợi sẽ thấy, nhưng quy trình cân bằng hao mòn chung và quy trình thử nghiệm là giống nhau cho cả hai. Nhiều nhà cung cấp không công bố liệu thiết bị của họ là SLC hay MLC cho các sản phẩm tiêu dùng rẻ hơn của họ, mặc dù bất kỳ ổ đĩa flash nào yêu cầu giới hạn chu kỳ 100k + trên mỗi trang đều có khả năng SLC (sự đánh đổi đơn giản là SLC = độ bền, MLC = mật độ).

Bộ nhớ đệm: Đối với bộ nhớ đệm, đó là một chút iffy. Ở cấp độ HĐH, trong trường hợp chung, dĩ nhiên, fsync / fdatasync không đảm bảo rằng dữ liệu thực sự được ghi. Tuy nhiên, tôi nghĩ an toàn khi cho rằng đó là (hoặc ít nhất là bộ điều khiển đã cam kết thực hiện điều đó tức là ghi sẽ không bị nuốt trong bộ đệm) trong trường hợp này, vì các ổ di động thường được thiết kế cho kiểu sử dụng chung của "Đẩy" (ngắt kết nối> đồng bộ hóa) rồi xóa (cắt điện). Mặc dù chúng tôi không biết chắc chắn, một phỏng đoán có giáo dục nói rằng sẽ an toàn khi cho rằng đồng bộ hóa đảm bảo rằng việc ghi sẽ hoàn toàn diễn ra, đặc biệt là trong ghi -> đồng bộ hóa -> đọc lại (nếu không, các ổ đĩa sẽ không đáng tin cậy sau khi đẩy ra). Không có lệnh nào khác ngoài 'đồng bộ hóa' có thể được ban hành khi đẩy ra.

Ở bộ điều khiển, mọi thứ đều có thể, nhưng giả định ở trên cũng bao gồm giả định rằng bộ điều khiển ít nhất không làm bất cứ điều gì "phức tạp" đủ để có nguy cơ mất dữ liệu sau khi đồng bộ hóa. Có thể hiểu rằng bộ điều khiển có thể, nói, bộ đệm và nhóm ghi hoặc không ghi dữ liệu nếu cùng một dữ liệu được viết lại (trong một phạm vi giới hạn). Trong chương trình bên dưới, chúng tôi luân phiên giữa hai khối dữ liệu khác nhau và thực hiện đồng bộ hóa trước khi đọc lại cụ thể để đánh bại cơ chế lưu trữ bộ điều khiển hợp lý. Tất nhiên, vẫn không có gì đảm bảo và không có cách nào để biết nhưng chúng ta có thể đưa ra các giả định hợp lý dựa trên việc sử dụng bình thường các thiết bị này và các cơ chế lưu trữ thông thường.

Kiểm tra:

Thật không may, sự thật là, trừ khi bạn biết rằng thiết bị không có không gian dành riêng và không thực hiện cân bằng tĩnh, không có cách nào để kiểm tra dứt khoát giới hạn chu kỳ của một trang cụ thể. Tuy nhiên, gần nhất bạn có thể nhận được như sau (giả sử không có mức độ hao mòn tĩnh):

Điều đầu tiên bạn cần làm là điền toàn bộ thẻ vào dữ liệu. Điều này rất quan trọng và là biến chính còn lại trong bài kiểm tra ban đầu của bạn. Điều này đánh dấu càng nhiều khối càng tốt khi được sử dụng, ngoài bất kỳ không gian dành riêng nào (mà bạn không có cách nào truy cập). Lưu ý rằng chúng tôi đang làm việc với toàn bộ thiết bị (điều này sẽ phá hủy tất cả dữ liệu trên), vì làm việc với một phân vùng duy nhất chỉ ảnh hưởng đến một khu vực cụ thể trên thiết bị:

dd if=/dev/urandom bs=512k of=/dev/sdb conv=fsync oflag=sync

Nếu bạn là loại thanh tiến trình:

pv -pterb -s <device_size> /dev/urandom | dd bs=512k of=/dev/sdb conv=fsync oflag=sync

Chỉnh sửa: Đối với thẻ có khối xóa 4 MB, hãy thử cách này để ghi nhanh hơn:

dd if=/dev/urandom bs=4M of=/dev/sdb conv=fsync oflag=direct,sync iflag=fullblock

Tiếp theo, sau đó, bạn có thể viết chương trình kiểm tra chu trình như sau, sử dụng O_DIRECTO_SYNC(và có thể là hoang tưởng, sử dụng dư thừa fsync()) để cắt càng nhiều bộ đệm hệ điều hành và bộ nhớ cache ra khỏi hình ảnh càng tốt và theo lý thuyết, hãy viết trực tiếp vào bộ điều khiển và đợi cho đến khi nó báo cáo rằng hoạt động đã kết thúc:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>

using namespace std;

static const int BLOCK_SIZE = 512;
static const int ALIGNMENT = 512;
static const int OFFSET = 1024 * ALIGNMENT; // 1024 is arbitrary


int main (int argc, char **argv) {

    if (argc != 2) {
        fprintf(stderr, "usage: %s device\n", argv[0]);
        return 1;
    }

    int d = open(argv[1], O_RDWR | O_DIRECT | O_SYNC);
    if (d == -1) {
        perror(argv[1]);
        return 1;
    }

    char *block[2], *buffer;
    int index = 0, count = -1;

    // buffers must be aligned for O_DIRECT.
    posix_memalign((void **)&(block[0]), ALIGNMENT, BLOCK_SIZE);
    posix_memalign((void **)&(block[1]), ALIGNMENT, BLOCK_SIZE);
    posix_memalign((void **)&buffer, ALIGNMENT, BLOCK_SIZE);

    // different contents in each buffer
    memset(block[0], 0x55, BLOCK_SIZE);
    memset(block[1], 0xAA, BLOCK_SIZE);

    while (true) {

        // alternate buffers
        index = 1 - index;

        if (!((++ count) % 100)) {
            printf("%i\n", count);
            fflush(stdout);
        }

        // write -> sync -> read back -> compare
        if (lseek(d, OFFSET, SEEK_SET) == (off_t)-1)
            perror("lseek(w)");
        else if (write(d, block[index], BLOCK_SIZE) != BLOCK_SIZE)
            perror("write");
        else if (fsync(d))
            perror("fsync");
        else if (lseek(d, OFFSET, SEEK_SET) == (off_t)-1)
            perror("lseek(r)");
        else if (read(d, buffer, BLOCK_SIZE) != BLOCK_SIZE)
            perror("read");
        else if (memcmp(block[index], buffer, BLOCK_SIZE))
            fprintf(stderr, "memcmp: test failed\n");
        else
            continue;

        printf("failed after %i successful cycles.\n", count);
        break;

    }

}

Lưu ý rằng đối với O_DIRECT, bộ đệm phải được căn chỉnh phù hợp. Ranh giới 512 byte nói chung là đủ. Bạn có thể biên dịch với:

g++ -O0 test.cpp -o test

Thêm -D_POSIX_C_SOURCE=200112Lnếu cần thiết.

Sau đó, sau khi lấp đầy thiết bị như trên, chỉ cần để thiết bị chạy qua đêm:

./test /dev/sdb

512 byte, ghi liên kết là tốt, nó sẽ cung cấp cho bạn toàn bộ một trang bị xóa và viết lại. Bạn có thể tăng tốc đáng kể bài kiểm tra bằng cách sử dụng kích thước khối lớn hơn, nhưng sau đó nó trở nên phức tạp để đi đến kết quả cụ thể.

Tôi hiện đang thử nghiệm trên một ổ ngón tay cái 4GB PNY trông khá nổi bật mà tôi tìm thấy trên vỉa hè ngày hôm qua (dường như là những gì còn lại của một http://www3.pny.com/4GB-Micro-Sleek-Attach-- -Purple-P2990C418.aspx ).

Chương trình trên về cơ bản là một phiên bản giới hạn badblocksvà bạn sẽ không thấy thất bại cho đến khi tất cả không gian dành riêng đã cạn kiệt. Do đó, kỳ vọng (với 1 trang được viết trên mỗi lần lặp) là quy trình trên, trung bình, sẽ thất bại trong các lần lặp dành riêng_page_count * write_ Motorcycle_limit (một lần nữa, mức độ hao mòn là một biến số chính). Ổ đĩa quá nhỏ và thẻ SD thường không hỗ trợ SMART, có khả năng báo cáo kích thước không gian dành riêng.

Nhân tiện, fsyncvs fdatasynckhông tạo ra sự khác biệt cho thiết bị khối mà bạn đang làm, cho mục đích của bài kiểm tra này. open()Chế độ của bạn rất quan trọng.

Nếu bạn tò mò về các chi tiết kỹ thuật; đây là tất cả mọi thứ bạn có thể muốn biết (cộng thêm) về hoạt động bên trong của thẻ SD: https://www.sdcard.org/doads/pls/simplified_specs/part1_410.pdf

Chỉnh sửa: Byte vs Pages: Trong ngữ cảnh của các loại thử nghiệm này, điều quan trọng là phải nghĩ về mọi thứ theo các trang, không phải byte. Nó có thể rất sai lệch để làm ngược lại. Ví dụ: trên SD SD SanDisk, kích thước trang theo bộ điều khiển (có thể truy cập qua /sys/classes/mmc_host/mmc?/mmc?:????/preferred_erase_size) là 4MB. Viết 16MB (căn chỉnh đến ranh giới 4 MB), sau đó, xóa / ghi 4 trang. Tuy nhiên, việc viết bốn byte đơn mỗi byte ở mức bù 4 MB cho nhau cũng xóa / ghi 4 trang.

Điều đó là không chính xác, sau đó nói "Tôi đã thử nghiệm với 16 MB ghi", vì nó có cùng mức độ hao mòn như "Tôi đã thử nghiệm với ghi 4 byte". Chính xác hơn, "Tôi đã thử nghiệm với 4 trang viết".


Tôi đã thêm một bình luận liên quan đến byte so với các trang.
Jason C

PNY xuất hiện không thể phá hủy. Tuy nhiên, sau ~ 8.1 triệu lần lặp (hơn 8 giờ) trên MicroSD SanDisk 8GB hoàn toàn mới, tiếp theo là chu kỳ năng lượng, tốc độ ghi tối đa (ban đầu là 4MB / giây) giảm vĩnh viễn xuống ~ 410kB / giây và ddthất bại sau khi ghi 250MB . Các thiệt hại đã không xuất hiện cho đến sau chu kỳ điện. Ổ ngón tay cái PNY vẫn không bị ảnh hưởng sau ~ 30 triệu lần lặp. Tuy nhiên, tôi đã sửa đổi chương trình ở trên (tuy nhiên không được phản ánh trong mã ở trên) để ghi vào các vị trí được căn chỉnh 16kB ngẫu nhiên mỗi lần thay vì giống nhau, nhưng tôi đã làm điều đó sau ~ 4 triệu phút trên SD. Sẽ thi lại bằng thẻ mới.
Jason C

Lần thử thứ ba ddtrên thẻ đó đã vượt qua mốc 250 MB và hiệu suất ghi lại tăng lên 4MB / giây đầy đủ cho các khu vực sau thời điểm đó. Tuy nhiên, tôi hy vọng hiệu suất sẽ không thể đoán trước được, vì các khối tiếp tục bị xáo trộn. Tôi sẽ không nói rằng thẻ bị phá hủy, nhưng nó chắc chắn không phải là 100%.
Jason C

5

Chỉ cần thêm một số điểm vào câu trả lời của slm - lưu ý rằng những điều này phù hợp với SSD hơn là cho thẻ SD "câm", vì SSD chơi nhiều thủ đoạn bẩn hơn với dữ liệu của bạn (ví dụ: sao chép lại):

  • bạn đang ghi 64KB vào đầu thiết bị - bản thân nó có hai vấn đề:

    1. các tế bào flash thường có các khối xóa có kích thước từ 16KB trở lên (nhiều khả năng trong phạm vi 128-512KB). Điều đó có nghĩa là nó cần bộ nhớ cache có kích thước tối thiểu. Do đó, viết 64KB dường như không đủ với tôi.

    2. đối với các giải pháp cấp thấp (đọc "phi doanh nghiệp") (và tôi mong đợi điều này thậm chí còn nhiều hơn đối với thẻ SD / CF so với SSD), các nhà sản xuất có thể chọn làm cho thiết bị bắt đầu dễ bị mòn hơn so với phần còn lại kể từ khi cấu trúc quan trọng - bảng phân vùng và FAT trên phân vùng đơn trên thiết bị (hầu hết các thẻ nhớ đang sử dụng thiết lập này) - được đặt ở đó. Do đó, việc kiểm tra đầu thẻ có thể bị sai lệch.

  • fdatasync() không thực sự đảm bảo rằng dữ liệu được ghi vào phương tiện vật lý (mặc dù nó có thể làm tốt nhất những gì nằm dưới sự kiểm soát của HĐH) - xem trang hướng dẫn:

    Các cuộc gọi chặn cho đến khi thiết bị báo cáo rằng việc chuyển hoàn thành

    Tôi sẽ không quá ngạc nhiên nếu hóa ra có một tụ điện nhỏ, có khả năng cung cấp năng lượng để ghi dữ liệu được lưu vào bộ nhớ flash trong trường hợp mất nguồn ngoài.

    Trong mọi trường hợp, theo giả định có bộ đệm trong thẻ (xem câu trả lời của tôi cho câu hỏi của bạn trên SU ), viết 64KB và đồng bộ hóa (vớifdatasync() ) dường như không đủ sức thuyết phục cho mục đích này. Ngay cả khi không có bất kỳ "dự phòng năng lượng" nào, phần sụn vẫn có thể phát nó không an toàn và giữ cho dữ liệu không được ghi lại lâu hơn một chút so với mong đợi (vì trong các trường hợp sử dụng thông thường, nó không tạo ra bất kỳ vấn đề nào).

  • bạn có thể muốn đọc dữ liệu trước khi viết khối mới và so sánh nó, chỉ để đảm bảo nó thực sự hoạt động (và sử dụng bộ đệm đã xóa để đọc, nếu bạn đủ hoang tưởng).


+1 Để làm nổi bật khả năng của bộ đệm và tầm quan trọng của khối xóa trong phần này. Nhưng ...
goldilocks

"kiểm tra sự khởi đầu của thẻ có thể bị sai lệch" Hãy nhớ, vì mức độ hao mòn (phải diễn ra - tôi đã vượt quá bất kỳ số lượng chu kỳ ghi hợp lý nào tại thời điểm này) - đây chỉ khối đầu tiên. Tức là, đó là khối ảo đầu tiên, không phải khối vật lý đầu tiên .
goldilocks

"fdatasync () không thực sự đảm bảo rằng dữ liệu được ghi vào phương tiện vật lý" IMO, thiết bị báo cáo rằng quá trình chuyển đã hoàn thành cho thấy việc ghi phải xảy ra nếu thiết bị cũng vượt qua các bài kiểm tra đọc-ghi thất bại một lần nào). Bộ nhớ đệm có thể làm phức tạp điều này, nhưng nếu chúng ta sử dụng một khối lớn tương đối để khắc phục điều đó, thì không thể có "ghi sai" khi thiết bị đã báo cáo thành công. Sẽ là vô ích nếu nó làm điều đó.
goldilocks

1
@goldilocks không, đọc dữ liệu từ thiết bị không đảm bảo bất cứ điều gì. Thật hợp lý khi hy vọng dữ liệu sẽ ở trên phương tiện vật lý và có thể nó sẽ có trong hầu hết các trường hợp, nhưng nó không được bảo đảm - ít nhất là trừ khi bạn vượt quá kích thước bộ đệm.
peterph

1
@goldilocks peterph mang đến một điều khác mà tôi đã muốn chỉ ra; các readtrong thử nghiệm của bạn là không cần thiết, nó không có thêm thông tin và không liên quan đến một bài kiểm tra ghi chu kỳ. Đối với một bài kiểm tra thực sự, bạn sẽ muốn đọc lại khối bạn vừa viết và xác thực nó, trừ khi bạn biết chắc chắn rằng bộ điều khiển có thể phát hiện và báo cáo lại tất cả các chế độ lỗi.
Jason C

2

Câu trả lời của Peterph đã khiến tôi xem xét vấn đề về bộ nhớ đệm có thể hơn nữa. Sau khi đào bới xung quanh, tôi vẫn không thể nói chắc chắn liệu có, một số hoặc tất cả các thẻ SD làm điều này không, nhưng tôi nghĩ điều đó là có thể.

Tuy nhiên, tôi không tin rằng bộ nhớ đệm sẽ liên quan đến dữ liệu lớn hơn khối xóa. Để thực sự chắc chắn, tôi đã lặp lại thử nghiệm bằng cách sử dụng một đoạn 16 MB thay vì 64 kB. Đây là 1/250 tổng dung lượng của thẻ 4 GB. Phải mất ~ 8 giờ để làm điều này 10.000 lần. Nếu cân bằng hao mòn làm hết sức để truyền tải xung quanh, điều này có nghĩa là mọi khối vật lý sẽ được sử dụng 40 lần.

Đó không phải là nhiều, nhưng điểm ban đầu của thử nghiệm là chứng minh tính hiệu quả của việc cân bằng độ mòn bằng cách cho thấy rằng tôi không thể dễ dàng làm hỏng thẻ thông qua việc ghi lặp lại một lượng dữ liệu khiêm tốn vào cùng một vị trí (rõ ràng). IMO thử nghiệm 64 kB trước đây có lẽ là có thật - nhưng phải là 16 MB. Hệ thống đã chuyển dữ liệu sang phần cứng và phần cứng đã báo cáo ghi mà không gặp lỗi. Nếu đây là một sự lừa dối, thẻ sẽ không tốt cho bất cứ điều gì và nó không thể lưu vào bộ nhớ cache 16 MB ở bất cứ đâu ngoài bộ nhớ chính, đó là điều mà bài kiểm tra dự định sẽ nhấn mạnh.

Hy vọng, 10.000 lần ghi 16 MB mỗi lần là đủ để chứng minh rằng ngay cả trên thẻ thương hiệu tên dưới cùng (giá trị: 5 đô la CDN), chạy hệ thống tập tin gốc rw 24/7, ghi số lượng dữ liệu khiêm tốn hàng ngày sẽ không làm hao mòn thẻ một khoảng thời gian hợp lý. 10.000 ngày là 27 năm ... và thẻ vẫn ổn ...

Nếu tôi được trả tiền để phát triển các hệ thống hoạt động nặng hơn thế, tôi sẽ muốn thực hiện ít nhất một vài thử nghiệm để xác định thẻ có thể tồn tại bao lâu . Linh cảm của tôi là với một cái như thế này, có tốc độ viết thấp, có thể mất hàng tuần, hàng tháng hoặc hàng năm để viết liên tục ở tốc độ tối đa (thực tế không có nhiều bài kiểm tra so sánh trực tuyến này nói với thực tế rằng nó sẽ là một chuyện rất kéo dài).

Đối với việc xác nhận thẻ vẫn ổn, tôi không còn nghĩ sử dụng badblockscấu hình mặc định của nó là phù hợp. Thay vào đó, tôi đã làm theo cách này:

badblocks -v -w -b 524288 -c 8

Có nghĩa là kiểm tra bằng cách sử dụng khối 512 kB được lặp lại 8 lần (= 4 MB). Vì đây là một thử nghiệm rw phá hủy, có lẽ nó sẽ tốt khi tôi thử nghiệm về việc làm căng thiết bị nếu sử dụng trong một vòng lặp liên tục.

Tôi cũng đã tạo một hệ thống tệp trên đó, được sao chép trong tệp 2 GB, đó difflà tệp so với bản gốc và sau đó - vì tệp là tệp .iso - gắn nó dưới dạng hình ảnh và duyệt hệ thống tệp bên trong đó.

Thẻ vẫn ổn. Điều mà có lẽ được mong đợi, sau tất cả ...

;);)


Tôi không nghĩ rằng toán học của bạn là đúng. Thẻ Class 2 có lưu lượng duy trì 2MB / s, điều đó có nghĩa là bạn sẽ đặt 20TB trong khoảng 4 tháng. Chắc chắn, bạn đã đề cập rằng bạn có một thẻ không được phân loại, nhưng bạn thực sự dường như là những đơn đặt hàng lớn (như terdon đã chỉ ra trong unix.stackexchange.com/questions/84902/ .). Nếu không tôi hoàn toàn đồng ý với slm.
peterph

Tôi tin rằng chúng ta có thể chắc chắn một cách hợp lý rằng bộ nhớ đệm có tác động tối thiểu, nếu có, tác động sau khi đồng bộ hóa cho phương tiện được thiết kế để thường xuyên được gỡ bỏ và cũng được cung cấp cho xe buýt. Hãy xem xét rằng các thiết bị này được thiết kế để "loại bỏ" một cách đáng tin cậy và loại bỏ, và rằng đồng bộ hóa là điều cuối cùng tuyệt đối mà HĐH có thể làm với một thiết bị khác ngoài việc cắt giảm sức mạnh của nó (nếu có thể). Thật hợp lý khi giả sử rằng, ví dụ như ổ USB hoặc thẻ SD được ghi bằng vật lý sau khi đồng bộ hóa hoặc tối thiểu cam kết thực hiện ghi trong một khoảng thời gian cực ngắn sau khi tắt nguồn.
Jason C

Ngoài ra, btw, badblockssẽ không hiển thị cho bạn các trang bị lỗi trên bộ nhớ flash. Nó không phải là công cụ phù hợp cho công việc này và bạn không thể sử dụng nó để tìm các trang bị lỗi trên flash. Khi bộ điều khiển phát hiện lỗi, nó sẽ đánh dấu trang bên trong là xấu và ánh xạ lại vào một trang trong không gian dành riêng. Tất cả điều này xảy ra đằng sau bộ điều khiển và bạn không thể nhìn thấy, ngay cả trong một bãi chứa thiết bị thô . Bạn có thể nhận được một số thông tin từ bộ điều khiển nếu SMART được hỗ trợ. Thứ tự vật lý của dữ liệu trên thiết bị không khớp với thứ tự byte bạn thấy khi thực hiện IO trên thiết bị.
Jason C

Thêm một nhận xét, nhiều hơn một FYI: trên MicroSD SanDisk 8GB, cấp độ người tiêu dùng, đơn vị phân bổ (tức là kích thước trang) là 4 MB như bộ điều khiển báo cáo; nghĩa là 16 MB trên thẻ đó là 4 trang (5 nếu không được căn chỉnh). Bạn có thể tăng tốc độ kiểm tra đó bằng cách ghi 512 byte với giá trị bù 4 MB cho nhau thay vì nạp 16 MB vào thẻ. Bạn không tạo ra sự khác biệt giữa byte và số lượng trang nhưng bạn nên - trong ví dụ của bạn, nếu nó nằm trên thẻ SanDisk 8GB, "16MB" đặt cùng mức hao mòn trên thẻ là "2KB". Rất sai lầm khi đề cập đến byte thay vì các trang.
Jason C

Sau ~ 8.1 triệu lần lặp (hơn 8 giờ) trong chương trình thử nghiệm mà tôi đã viết ở trên, tiếp theo là chu kỳ năng lượng, trên MicroSD SanDisk 8GB hoàn toàn mới, tốc độ ghi bị giới hạn vĩnh viễn khoảng 450kB / giây và ddkhông thể ghi được khoảng 250MB dấu. Trong lần ddthử thứ ba, nó đã vượt quá 250 MB và sau khi thực hiện, hiệu suất ghi lại tăng lên trong các khu vực đó. Tôi sẽ không nói rằng thẻ bị phá hủy nhưng nó chắc chắn không phải là 100%.
Jason C
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.