@Vadimatorikda
Инженер-программист, embedded разработчик

Почему файл после многократного количество циклов записи перестает быть доступен для открытия (fopen)?

Здравствуйте. Задача - открывать файл-образ fat32 flash накопителя и читать/записывать данные и него/в него. Данные читаются или записываются блоками по 512 * n байт. Выхода за пределы файла гарантировано быть не может (по сути, имитируется доступ к аппаратному flash накопителю, с которым работает fatfs).
Имеется:
Операционная система: Ubuntu 18.04.3 LTS, x64
Файл (образ fat32 micro-sd на 256 мегабайт), созданный следующей последовательностью команд:
$ sudo dd if=/dev/zero of=microsd.img bs=512 count=524288
$ sudo mkfs.fat -F32 -v -I microsd.img
$ sudo chmod 777 microsd.img
$ sudo chown user_name:user_name microsd.img

Программа собирается с флагами:
-m32 -O0 -g3 -fdata-sections -ffunction-sections -Wl,--gc-sections  -std=gnu99

Программа должна быть обязательно собрана под x32, по-этому флаг -m32 обязателен (целевая платформа 32-х битная).

Файл успешно создается, его чтение-запись из системы происходит успешно на всем объеме (скидывал на накопитель файл близкий ко всему объему и вычитывал обратно).
Чтение/запись в файл/из файла осуществляется следующим кодом:
// Путь до файла верный, работа ведется только с 1 файлом.
const char FILE_MICROSD_PATH[] = "../resurse/microsd.img";

// Размер блока стандартные 512 байт.
#define SD_BLOCK_SIZE 512
static FILE *sd = NULL;

int sdio_write (const uint32_t *buf, uint32_t block_num, uint32_t num_block) {
    if ((sd = fopen(FILE_MICROSD_PATH, "r+b")) == NULL) {
        return -1;
    };

    if (fseek(sd, block_num*SD_BLOCK_SIZE, SEEK_SET) != 0) {
        fclose(sd);
        sd = NULL;
        return -1;
    }

    if (fwrite(buf, SD_BLOCK_SIZE, num_block, sd) != num_block) {
        fclose(sd);
        sd = NULL;
        return -1;
    };

    int rv = fclose(sd);
    sd = NULL;
    return rv;
}

int sdio_read (uint32_t *buf, uint32_t block_num, uint32_t num_block) {
if ((sd = fopen(FILE_MICROSD_PATH, "r+b")) == NULL) {
        return -1;
    };

    if (fseek(sd, block_num*SD_BLOCK_SIZE, SEEK_SET) != 0) {
        fclose(sd);
        sd = NULL;
        return -1;
    }

    if (fread(buf, SD_BLOCK_SIZE, num_block, sd) != num_block) {
        fclose(sd);
        sd = NULL;
        return -1;
    };

    int rv = fclose(sd);
    sd = NULL;
    return rv;
}

Если запустить запись множество раз подряд, то в какой-то момент при следующем открытии файла fopen будет возвращать ошибку. Всегда на одном и том же месте при запуске без отладки. Однако, если включить отладку и ставить точку остановки перед открытием файла, то весь цикл открытия, записи или чтения будет проходить успешно и никаких ошибок не будет. Отсюда напрашивается желание поставить некоторую задержку после закрытия файла. Например, 100 миллисекунд. Но это не спасает ситуацию (да и не правильно). Если какой-то способ решить данную проблему нормальными способами? Может есть функция, сообщающая о том, что файл действительно был закрыт и к нему можно обратиться снова или что0то подобное?
P.S. Файл гарантировано закрывается после каждого обращения, возвращая при этом флаг успешного закрытия.
  • Вопрос задан
  • 328 просмотров
Решения вопроса 1
@Karpion
Исследовать код завершения оператора fopen().
Проверить, как оно работает при задержке "100 миллисекунд" или больше.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы