Diferencia entre fflush y fsync
windows (5)
Pensé que fsync () tiene fflush () internamente, por lo que usar fsync () en una secuencia es correcto. Pero estoy obteniendo resultados inesperados cuando se ejecutan en la red de E / S.
Mi fragmento de código:
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);
Pero parece que _commit () no está limpiando los datos (lo intenté en Windows y los datos se escribieron en un sistema de archivos exportado por Linux).
Cuando cambié el código como:
FILE* fp = fopen(file,"wb");
/* multiple fputs() call like: */
fputs(buf, fp);
...
...
fputs(buf.c_str(), fp);
/* fflush the data */
fflush(fp);
fclose(fp);
Esta vez borra los datos.
Me pregunto si _commit () hace lo mismo que fflush (). ¿Alguna entrada?
Podría decir eso por simplicidad:
use fsync()
sin archivos de transmisión (descriptores de archivos enteros)
use fflush()
con las secuencias de archivos.
También aquí está la ayuda del hombre:
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
Para forzar el compromiso de los cambios recientes en el disco, use las funciones sync () o fsync ().
fsync () sincronizará todos los datos y metadatos del archivo dado con el dispositivo de almacenamiento permanente. Se debe llamar justo antes de que se haya cerrado el archivo correspondiente.
sync () confirmará todos los archivos modificados en el disco.
fflush()
funciona en FILE*
, simplemente vacía los búferes internos en el FILE*
de su aplicación al SO.
fsync
funciona en un nivel inferior, le dice al sistema operativo que descargue sus almacenamientos intermedios a los medios físicos.
Los SO almacenan en caché los datos que escribe en un archivo. Si el sistema operativo aplicara cada escritura para golpear el disco, las cosas serían muy lentas. fsync
(entre otras cosas) le permite controlar cuándo los datos deberían golpear la unidad.
Además, fsync / commit funciona en un descriptor de archivo. No tiene conocimiento de un FILE*
y no puede vaciar sus búferes. FILE*
vive en su aplicación, los descriptores de archivos en vivo en el núcleo del sistema operativo, por lo general.
La función C estándar fflush()
y la llamada al sistema POSIX fsync()
son conceptualmente similares. fflush()
opera en secuencias de archivos C (objetos FILE
) y, por lo tanto, es portátil. fsync()
opera en los descriptores de archivos POSIX. Ambos hacen que los datos almacenados en el búfer se envíen a un destino.
En un sistema POSIX, cada flujo de archivo C tiene un descriptor de archivo asociado , y todas las operaciones en una secuencia de archivo C se implementarán mediante la delegación, cuando sea necesario, a las llamadas al sistema POSIX que operan en el descriptor de archivo.
Se podría pensar que una llamada a fflush
en un sistema POSIX provocaría una write
de cualquier dato en el búfer de la secuencia de archivos, seguido de una llamada de fsync()
para el descriptor de archivo de esa secuencia de archivos. Por lo tanto, en un sistema POSIX no habría necesidad de seguir una llamada para fflush
con una llamada a fsync(fileno(fp))
. Pero ese es el caso: ¿hay una llamada a fsync
desde fflush
?
No, llamar a fflush
en un sistema POSIX no implica que se llame a fsync
.
El estándar C para fflush
dice (énfasis agregado)
hace que cualquier dato no escrito para [la] secuencia entregada al entorno de host se escriba en el archivo
Decir que los datos deben escribirse, en lugar de que se haya escrito, implica que se permite un mayor almacenamiento en memoria intermedia por parte del entorno host. Ese almacenamiento en búfer por parte del "entorno de host" podría incluir, para un entorno POSIX, el almacenamiento en búfer interno que se descarga fsync
. Entonces, una lectura atenta del estándar C sugiere que el estándar no requiere que la implementación POSIX llame a fsync
.
La descripción estándar POSIX de fflush
no declara, como una extensión de la semántica C , que se llama fsync
.
Creo que el documento a continuación de python ( https://docs.python.org/2/library/os.html ) lo aclara muy bien.
os.fsync (fd) Forzar la escritura del archivo con el descriptor de archivo fd en el disco. En Unix, esto llama a la función nativa fsync (); en Windows, la función MS _commit ().
Si está comenzando con un objeto de archivo de Python f, primero haga f.flush () y luego haga os.fsync (f.fileno ()), para asegurarse de que todos los búferes internos asociados con f se escriben en el disco.
Disponibilidad: Unix y Windows a partir de 2.2.3.