Разница между fflush и fsync

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

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

FILE* fp = fopen(file,"wb");
/* multiple fputs() call 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() call like: */
fputs(buf, fp);   
...   
...
fputs(buf.c_str(), fp);
/* fflush the data */
fflush(fp);
fclose(fp);

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

мне интересно, если _commit() делает то же самое, что и fflush(). Какие входы?

5 ответов


fflush() работает на FILE*, Он просто сбрасывает внутренние буферы в FILE* вашего приложения в ОС.

fsync работает на более низком уровне, он говорит ОС, чтобы очистить свои буферы на физические носители.

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

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


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

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

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

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

стандарт C для fflush говорит (Курсив мой) это

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

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

на стандартное описание POSIX fflush не объявляет, как расширение семантики C, что 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

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

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

sync () будет сохранить все измененные файлы на диск.


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

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

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

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