Вопрос

Я думал fsync() делает fflush() внутренне, поэтому использование fsync() в потоке - это нормально.Но я получаю неожиданный результат при выполнении в режиме сетевого ввода-вывода.

Мой фрагмент кода:

FILE* fp = fopen(file, "wb");
/* multiple fputs() calls like: */
fputs(buf, fp);
...
...
fputs(buf.c_str(), fp);
/* get fd of the FILE pointer */
fd = fileno(fp);
#ifndef WIN32
ret = fsync(fd);
#else
ret = _commit(fd);
fclose(fp);

Но это кажется _commit() не удаляет данные (я пробовал в Windows, и данные были записаны в экспортированную файловую систему Linux).

Когда я изменил код, чтобы быть:

FILE* fp = fopen(file, "wb");
/* multiple fputs() calls like: */
fputs(buf, fp);   
...   
...
fputs(buf.c_str(), fp);
/* fflush the data */
fflush(fp);
fclose(fp);

он сбрасывает данные.

Мне интересно, если _commit() делает то же самое , что и fflush().Есть какие-нибудь исходные данные?

Это было полезно?

Решение

fflush() работает над FILE*, он просто очищает внутренние буферы в FILE* из вашего приложения в операционную систему.

fsync работает на более низком уровне, он сообщает операционной системе сбросить свои буферы на физический носитель.

Операционные системы сильно кэшируют данные, которые вы записываете в файл.Если бы ОС принудительно выполняла каждую запись для попадания на диск, все было бы очень медленно. fsync (среди прочего) позволяет вам контролировать, когда данные должны попасть на диск.

Кроме того, fsync /commit работает с файловым дескриптором.Он не имеет никакого представления о FILE* и не может очистить его буферы. FILE* живет в вашем приложении, файловые дескрипторы, как правило, живут в ядре операционной системы.

Другие советы

Стандартная функция C fflush() и системный вызов POSIX fsync() концептуально они в чем-то схожи. fflush() работает с файловыми потоками C (FILE объекты), и поэтому является переносимым.fsync() оперируйте файловыми дескрипторами POSIX.И то, и другое приводит к отправке буферизованных данных в пункт назначения.

В системе POSIX каждый поток файлов C имеет связанный файловый дескриптор, и все операции с файловым потоком C будут реализованы путем делегирования, при необходимости, системным вызовам POSIX, которые работают с файловым дескриптором.

Можно было бы подумать, что призыв к fflush в системе POSIX это привело бы к write любых данных в буфере файлового потока, за которым следует вызов fsync() для файлового дескриптора этого файлового потока.Таким образом, в системе POSIX не было бы необходимости следовать вызову fflush с призывом к fsync(fileno(fp)).Но так ли это на самом деле:есть ли призыв к fsync От fflush?

Нет, звоню fflush в системе POSIX не подразумевает, что fsync будет вызван.

Стандарт C для fflush говорит (курсив мой добавлен), что это

вызывает доставку любых неписаных данных для потока [the] в среду хоста быть написанным к файлу

Говоря, что данные являются быть написано, а не то, что есть является записанный подразумевает, что разрешена дальнейшая буферизация средой хоста.Эта буферизация "средой хоста" может включать в себя, для среды POSIX, внутреннюю буферизацию, которая fsync приливы.Таким образом, внимательное прочтение стандарта C предполагает, что стандарт не требует, чтобы реализация POSIX вызывала fsync.

В Стандартное описание POSIX для fflush не объявляет, как расширение семантики языка Си, что fsync называется.

Я мог бы сказать это для простоты:

использование fsync() с файлами, не являющимися потоковыми (целочисленные файловые дескрипторы)

использование fflush() с файловыми потоками.

Также здесь есть помощь от мужчины:

int fflush(FILE *stream); // flush a stream, FILE* type

int fsync(int fd); // synchronize a file's in-core state with storage device
                    // int type

fflush() и fsync() может использоваться для проверки того, что данные записаны на носитель (но это не всегда возможно).:

  1. первое использование fflush(fp) в выходном потоке (fp будучи FILE * получено из fopen или один из стандартных потоков stdout или stderr) для записи содержимого буфера, связанного с потоком, в операционную систему.
  2. затем используйте fsync(fileno(fp)) чтобы сообщить операционной системе записать свои собственные буферы на носитель данных.

Однако обратите внимание, что fileno() и fsync() существуют ли функции POSIX, которые могут быть недоступны во всех системах, особенно в устаревших системах Microsoft, где могут быть названы альтернативы _fileno(), _fsync() или _commit()...

Чтобы принудительно перенести последние изменения на диск, используйте функции sync() или fsync().

fsync() синхронизирует все данные данного файла и метаданные с устройством постоянного хранения.Он должен быть вызван непосредственно перед закрытием соответствующего файла.

синхронизация () сохранит все измененные файлы на диск.

Я думаю, что приведенный ниже документ из python (https://docs.python.org/2/library/os.html) проясняет это очень хорошо.

os.fsync (fd) Принудительно записывает файл с помощью filedescriptor fd на диск.В Unix это вызывает встроенную функцию fsync();в Windows используется функция MS _commit().

Если вы начинаете с файлового объекта Python f, сначала выполните f.flush(), а затем выполните os.fsync(f.fileno()), чтобы убедиться, что все внутренние буферы связанные с f записываются на диск.

Доступность:Unix и Windows, начиная с версии 2.2.3.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top