Search code examples
fflushfsynccwindows

Difference between fflush and fsync


I thought fsync() does fflush() internally, so using fsync() on a stream is OK. But I am getting an unexpected result when executed under network I/O.

My code snippet:

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);

But it seems _commit() is not flushing the data (I tried on Windows and the data was written on a Linux exported filesystem).

When I changed the code to be:

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

it flushes the data.

I am wondering if _commit() does the same thing as fflush(). Any inputs?


Solution

  • fflush() works on FILE*, it just flushes the internal buffers in the FILE* of your application out to the OS.

    fsync works on a lower level, it tells the OS to flush its buffers to the physical media.

    OSs heavily cache data you write to a file. If the OS enforced every write to hit the drive, things would be very slow. fsync (among other things) allows you to control when the data should hit the drive.

    Furthermore, fsync/commit works on a file descriptor. It has no knowledge of a FILE* and can't flush its buffers. FILE* lives in your application, file descriptors live in the OS kernel, typically.