У меня есть программа, которая вызывается по сценарию. Эта программа записывает большой объем данных в файл на диске, а затем завершает свою работу. Как только он будет запущен, скрипт отключит питание всей системы.
Проблема, с которой я столкнулся, заключается в том, что файл не записывается полностью. Если это файл размером 4 ГБ, на самом деле на диске будет только около 2 ГБ, когда я буду просматривать его позже. Единственный способ, которым я смог надежно убедиться, что все данные записаны, - это засыпать программу на небольшой период перед выходом, но это действительно плохой и ненадежный прием, который я не хочу использовать. Вот пример кода моей последней попытки:
int main () {
FILE *output;
output = fopen("/logs/data", "w");
[fwrite several GiB of data to output]
fflush(output);
int fdo = open("/logs", O_RDONLY);
fsync(fdo);
fclose(output);
close(fdo);
return 0;
}
Сначала я попытался создать свой ФАЙЛ с файловым дескриптором и вызвать fsync () для используемого дескриптора (/ logs / data), однако это вызвало ту же проблему. Согласно спецификации для fsync (2) :
Вызов fsync () не обязательно гарантирует, что запись в каталоге, содержащем файл, также достигла диска. Для этого также необходима явная fsync () для файлового дескриптора каталога.
который привел меня к приведенному выше коду, создав специальный дескриптор файла только для каталога, содержащего мой файл данных, и вызвал для него fsync (). Однако результаты были такими же. Я действительно не понимаю, почему это происходит, потому что fsync () должен блокировать:
Вызов блокируется до тех пор, пока устройство не сообщит о завершении передачи.
кроме того, как вы можете видеть, я добавил fflush () в ФАЙЛ, думая, что, возможно, fsync () синхронизирует только данные, которые ранее были сброшены, но это не повлияло на ситуацию.
Мне нужно как-то убедиться, что данные действительно были записаны на физический носитель, прежде чем завершить программу, и я не уверен, как это сделать. Я вижу, что есть некоторые файлы, такие как / sys / block / [device] / [partition] / stat, которые могут сказать мне, сколько грязных блоков осталось записать, и я могу дождаться, пока это значение достигнет 0, но это не так. кажется отличным способом решить, что должно быть простой проблемой, и, кроме того, если на диске работает какая-либо другая программа, я не хочу ждать, пока они синхронизируют свои данные, так как меня волнует только целостность этот конкретный файл и файл stat не различаются.
ИЗМЕНИТЬ В соответствии с предложением я дважды попытался выполнить fsync (), сначала в файле, а затем в каталоге:
int main () {
FILE *output;
int fd = open("/logs/data", O_WRONLY | O_CREAT, 660);
output = fdopen(fd, "w");
[fwrite several GiB of data to output]
fsync(fd);
int fdo = open("/logs", O_RDONLY);
fsync(fdo);
fclose(output);
close(fd);
close(fdo);
return 0;
}
Это произвело интересный результат. При использовании файла размером 4 ГБ (4294967296 байт) фактический размер данных на диске составлял 4294963200, что как раз на 1 страницу файла (4096 байт) отличается от общего значения. Кажется, что это очень близкое к рабочему решению, но оно все еще не гарантирует каждый байт данных.
fsync(fileno(output))
? Открытие второго экземпляра файла может не завершить передачу. Ссылка: stackoverflow.com/questions/3167298/ - person Halt State   schedule 07.01.2021output
есть незаписанные данные, которые не записываются до вызоваfclose
. Попробуйте позвонитьfflush(output);
доfsync(fd);
. - person Ian Abbott   schedule 07.01.2021syncfs(fd)
после (или вместо)fsync(fd)
вместо того, чтобы возиться с каталогом. - person n. 1.8e9-where's-my-share m.   schedule 07.01.2021