Поиск сбойных секторов устройства в C

Я пытаюсь создать простой скрипт на c, который может идентифицировать поврежденные сектора (устройства) в образовательных целях. В моем примере я использую HD с режимом только для чтения. Идея проста, но, возможно, слишком проста, и я бы знал, правильно ли это, и в конечном итоге узнал бы о любом другом способе достижения моей цели.

Давайте посмотрим на мой код:

#include<stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char ** argcv){
        size_t size_block = 512;
        int fd = open("/dev/disk2",O_RDONLY);
        ssize_t bytes_read = 1;
        char *buff = malloc(size_block * sizeof(char));

        if (buff == NULL){
           exit(EXIT_FAILURE);
        }

        while (bytes_read > 0){
                bytes_read = read(fd,buff,size_block);
                int position = lseek(fd, 0, SEEK_CUR);
                if (bytes_read == -1){
                        perror("main");
                }
                //printf("%s",buff); //prints the content of what I read
                if (bytes_read < size_block){
                        printf("the block at %p address is probably damaged",&position);
                }
        }
        free(buff);
        close(fd);
        return 0;
}

Поэтому я пытаюсь читать сектора моего HD с помощью системных вызовов чтения, каждый раз ища указатель файла размером 512 байт. И это первый вопрос: так как предпочтительный размер блока ввода-вывода составляет 2048 байт (информация получена с помощью статистики sys/stat.h), правильно ли искать каждый раз 512 байт вместо 2048? Кроме того, чтобы проверить, является ли сектор плохим, я использую для сравнения (bytes_read < size_block), потому что я предполагаю, что если я не могу прочитать все байты сектора, он может быть поврежден. Но если я достигну конца файла, и он не кратен 512 с помощью этого метода, я получу, что сектор все равно поврежден, даже если это не так. То, что я написал, действительно работает? Иначе как я могу сделать эту проверку?


person Virgula    schedule 24.08.2020    source источник
comment
Всегда проверяйте, не возвращает ли malloc NULL   -  person Hawk    schedule 24.08.2020
comment
Нет смысла в malloc/free каждом цикле. Просто malloc один раз перед циклом. lseek возвращает off_t, а не int, а read возвращает ssize_t, а не int. И не приводить результат malloc и приведение (int)size_block тоже странно - убери это. И я не думаю, что следую операции read+lseek - read сама ищет курсор, поэтому, вызывая lseek, вы перемещаетесь на 2*size_block за раз.   -  person KamilCuk    schedule 24.08.2020
comment
Установка bytes_read в 1 только для того, чтобы цикл while выполнялся в первый раз... нелогичен. Просто используйте цикл do {} while вместо while{}   -  person Hawk    schedule 24.08.2020
comment
@Hawk Я забыл, спасибо.   -  person Virgula    schedule 24.08.2020
comment
@KamilCuk Вы уверены в этом поведении указателя чтения? Любая ссылка?   -  person Virgula    schedule 24.08.2020
comment
чтение posix The file offset shall be incremented by the number of bytes actually read.   -  person KamilCuk    schedule 24.08.2020
comment
@KamilCuk Хорошо, мне нужно только напечатать адрес fd. Спасибо.   -  person Virgula    schedule 24.08.2020


Ответы (1)


По крайней мере, в Linux я почти уверен, что блочное устройство всегда будет иметь читаемый размер, кратный 512 байтам, независимо от емкости базового устройства. Ядро заполняет последний блок, если физических данных недостаточно для заполнения 512 байт. Когда файловая система создается на устройстве, инструменты файловой системы округляют выделенный размер в меньшую сторону, чтобы учесть это.

Это означает, что read() размера 512 всегда будет возвращать 512 или ошибку, даже если это последнее чтение и оно не заполняет весь 512-байтовый буфер.

Однако я думаю, что маловероятно, что сбойный сектор вызовет короткое чтение. Я думаю, что более вероятно, что read() просто потерпит неудачу и вернет -1, или просто покажется успешным и вернет какую-то чепуху. Я подозреваю, что вам нужно писать и читать, чтобы проверить наличие битых секторов.

person Kevin Boone    schedule 24.08.2020
comment
Я подозреваю, что вам нужно писать и читать, чтобы проверить наличие поврежденных секторов. Но запись в сектора может заменить мои реальные данные, а программное обеспечение, такое как badblocks, этого не делает. ссылка (читайте в конце статьи: По умолчанию команда badblocks будет выполнять чтение- только тест.). Также взгляните на эту программу: github Первая функция гласит: сканирование плохих блоков только для чтения. Так что я думаю, что это возможно сделать. - person Virgula; 24.08.2020
comment
Если вы знаете утилиту, которая может делать то, что вы хотите, почему бы не связаться с автором? Однако я подозреваю, что тестирование только для чтения покажет плохие блоки только в том случае, если они уже были отмечены как плохие прошивкой или файловой системой накопителя. Такая маркировка обычно происходит во время исчерпывающего тестирования, но я думаю, что это также может произойти, если приложению не повезло записать блок, недоступный для записи. Я не думаю, что простое чтение может надежно найти плохие блоки, которые неизвестны системе, но я ошибался раньше. - person Kevin Boone; 24.08.2020
comment
Бывает так, что чтение может завершиться ошибкой, если микропрограмма накопителя сигнализирует об ошибке, скажем, в контрольной сумме блока. Это будет означать, что данные на диске ненадежны, но это не обязательно означает, что сектор нельзя использовать снова. Я действительно думаю, что вам нужно написать, чтобы определить это. Возможно, проблема здесь в отсутствии точного определения плохого. Несмотря на все это, я по-прежнему не думаю, что вам нужно беспокоиться о коротком прочтении, которое не является результатом дефекта, о чем, я думаю, вы изначально спрашивали. - person Kevin Boone; 24.08.2020
comment
Хорошо, моя первая идея заключалась в том, что под плохими секторами мы подразумеваем сектора, которые нельзя использовать ни для записи, ни для чтения независимо от определения плохих. На данный момент я понял, что довольно сложно точно определить, является ли сектор действительно плохим сектором или нет, поэтому я в любом случае буду удовлетворен, чтобы определить, какие сектора мы не можем прочитать независимо от состояния записи. - person Virgula; 24.08.2020
comment
Чтение завершится ошибкой, если блок получит неверные биты проверки, а микропрограмма накопителя не сможет восстановить данные. Как только блок помечен как плохой, для его записи будет использоваться запасной сектор, поэтому диск будет казаться восстановленным. Записи не проверяются, поэтому обычно не терпят неудачу. - person stark; 25.08.2020