Différence entre fflush et fsync
Question
Je pensais que fsync()
ne fflush()
en interne, donc l'utilisation fsync()
sur un cours d'eau est OK. Mais je reçois un résultat inattendu lorsqu'il est exécuté sous E / S réseau.
Mon extrait de code:
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);
Mais il semble _commit()
n'est pas le rinçage des données (j'ai essayé sur Windows et les données ont été écrites sur un système de fichiers exporté Linux).
Quand j'ai changé le code à:
FILE* fp = fopen(file, "wb");
/* multiple fputs() calls like: */
fputs(buf, fp);
...
...
fputs(buf.c_str(), fp);
/* fflush the data */
fflush(fp);
fclose(fp);
il évacue les données.
Je me demande si _commit()
fait la même chose que fflush()
. Toutes les entrées?
La solution
fflush()
fonctionne sur FILE*
, il débusque que les tampons internes dans le FILE*
de votre application vers le système d'exploitation.
fsync
fonctionne à un niveau inférieur, il indique le système d'exploitation pour vider ses tampons au support physique.
données fortement cache OSs vous écrire dans un fichier. Si le système d'exploitation appliqué chaque écriture pour frapper le lecteur, les choses seraient très lent. fsync
(entre autres) vous permet de contrôler quand les données doivent frapper le lecteur.
En outre, fsync / commit travaux sur un descripteur de fichier. Il n'a pas connaissance d'un FILE*
et ne peut pas vider ses tampons. vit FILE*
dans votre application, les descripteurs de fichiers en direct dans le noyau du système d'exploitation, généralement.
Autres conseils
La fonction standard C fflush()
et le fsync()
d'appel système POSIX sont conceptuellement quelque peu similaire. fflush()
fonctionne sur les flux de fichiers C (objets FILE
), et est par conséquent portable.
fsync()
agissent sur les descripteurs de fichiers POSIX.
Les deux causes données en mémoire tampon à envoyer à une destination.
Sur un système POSIX, chaque flux fichier C a un descripteur de fichier associé , et toutes les opérations sur un flux de fichier C seront mises en œuvre en déléguant, le cas échéant, aux appels système POSIX qui fonctionnent sur le descripteur de fichier.
On pourrait penser qu'un appel à fflush
sur un système POSIX entraînerait une write
de toutes les données dans la mémoire tampon du flux de fichiers, suivi d'un appel de fsync()
pour le descripteur de fichier de ce flux de fichiers. Donc, sur un système POSIX il n'y aurait pas besoin de suivre un appel à fflush
avec un appel à fsync(fileno(fp))
. Mais est-ce le cas: est-il un appel à fsync
de fflush
Non, appelant fflush
sur un système POSIX ne signifie pas que fsync
sera appelée.
La norme C pour fflush
dit (je souligne) il
que toutes les données non écrites pour [le] flux à livrer à l'environnement hôte à écrire dans le fichier
Dire que les données sont pour être écrit, plutôt que c'est écrit implique que davantage mise en mémoire tampon par l'environnement hôte est autorisé. Cette mise en mémoire tampon par le pourrait « environnement d'accueil » comprennent, pour un environnement POSIX, la mise en mémoire tampon interne qui fsync
flush. Ainsi, une lecture attentive de la norme C suggère que la norme ne nécessite pas la mise en œuvre de Posix appeler fsync
.
description standard POSIX fflush
ne déclare pas, comme , qui fsync
est appelée.
Je pourrais dire que pour la simplicité:
Utilisation fsync()
avec les fichiers de streaming (descripteurs de fichier entier)
Utilisation fflush()
avec des flux de fichiers.
Aussi est ici l'aide de l'homme:
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()
et fsync()
peuvent être utilisés pour essayer de garantir que les données sont écrites sur le support de stockage (mais il est pas toujours être possible):
-
fflush(fp)
première utilisation sur le flux de sortie (fp
étant unFILE *
obtenu à partir defopen
ou l'un des flux standardsstdout
oustderr
) pour écrire le contenu de la mémoire tampon associée au flux de l'OS. - utilisez
fsync(fileno(fp))
pour dire le système d'exploitation d'écrire ses propres tampons sur le support de stockage.
Notez cependant que fileno()
et fsync()
sont des fonctions POSIX qui pourraient ne pas être disponibles sur tous les systèmes, notamment les systèmes existants de Microsoft où les alternatives peuvent être nommés _fileno()
, _fsync()
ou _commit()
...
Pour forcer l'engagement des changements récents sur le disque, utilisez les fonctions de synchronisation () ou fsync ().
fsync () synchroniser toutes les données du fichier donné et métadonnées avec le dispositif de stockage permanent. Il devrait être appelé juste avant que le fichier correspondant a été fermé.
Synchronisation () engagera tous les fichiers modifiés sur le disque.
Je pense que ci-dessous le document de python ( https://docs.python.org/ 2 / bibliothèque / os.html ) clarifie très bien.
os.fsync (fd) écriture force de fichier avec FileDescriptor fd à disque. Sur Unix, cela appelle la fonction native fsync (); sous Windows, MS _commit fonction ().
Si vous commencez avec un objet fichier Python f, d'abord faire f.flush (), puis faire os.fsync (f.fileno ()), afin d'assurer que tous les tampons internes associé à f sont écrites sur le disque.
Disponibilité: Unix et Windows à partir de 2.2.3
.