Je pensais que fsync () utilisait fflush () en interne, donc utiliser fsync () sur un flux est correct. Mais j'obtiens un résultat inattendu lors de l'exécution sous les E/S du réseau.
Mon extrait de code:
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);
Mais il semble que _commit () ne vide pas les données (j'ai essayé sur Windows et les données ont été écrites sur le système de fichiers exporté par Linux).
Quand j'ai changé le code comme:
FILE* fp = fopen(file,"wb");
/* multiple fputs() call like: */
fputs(buf, fp);
...
...
fputs(buf.c_str(), fp);
/* fflush the data */
fflush(fp);
fclose(fp);
Cette fois, il vide les données.
Je me demande si _commit () fait la même chose que fflush (). Des entrées?
La fonction standard C fflush()
et l'appel système POSIX fsync()
sont conceptuellement assez similaires. fflush()
opère sur les flux de fichiers C (FILE
objets) et est donc portable .fsync()
opère sur les descripteurs de fichier POSIX .
Sur un système POSIX, chaque flux de fichiers C est associé à un descripteur de fichier , et toutes les opérations d’un flux de fichiers C sont implémentées en déléguant, le cas échéant, des appels système POSIX opérant sur le descripteur de fichier.
On pourrait penser qu'un appel à fflush
sur un système POSIX provoquerait une write
de toutes les données du tampon du flux de fichiers, suivie d'un appel de fsync()
pour le descripteur de fichier de ce flux de fichiers. Ainsi, sur un système POSIX, il ne serait pas nécessaire de suivre un appel à fflush
avec un appel à fsync(fileno(fp))
. Mais est-ce le cas: existe-t-il un appel à fsync
à partir de fflush
?
Non, appeler fflush
sur un système POSIX n'implique pas que fsync
sera appelé.
La norme C pour fflush
dit (c'est nous qui soulignons)
fait en sorte que toutes les données non écrites pour [le] flux soient transmises à l'environnement hôte à l'écriture dans le fichier
Dire que les données sont à écrire plutôt que est implique que la mise en mémoire tampon de l'environnement hôte est autorisée. Cette mise en mémoire tampon par "l'environnement hôte" peut inclure, pour un environnement POSIX, la mise en mémoire tampon interne qui fsync
vide. Une lecture attentive de la norme C suggère donc que la norme ne nécessite pas que l'implémentation POSIX appelle fsync
.
La description standard POSIX de fflush
ne déclare pas, comme une extension de la sémantique C , que fsync
est appelé.
Je pourrais dire cela pour plus de simplicité:
utiliser fsync()
avec les fichiers non en flux continu (descripteurs de fichiers entiers)
utilisez fflush()
avec les flux de fichiers.
Aussi voici 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
Je pense que le document ci-dessous de python ( https://docs.python.org/2/library/os.html ) le clarifie très bien.
os.fsync (fd) Forcer l’écriture du fichier avec filedescriptor fd sur le disque. Sur Unix, cela appelle la fonction native fsync (); sous Windows, le fichier MS fonction _commit ().
Si vous commencez avec un objet de fichier Python f, faites d’abord f.flush (), puis faites os.fsync (f.fileno ()), pour vous assurer que tous les tampons internes associés à f sont écrits sur le disque.
Disponibilité: Unix et Windows à partir de 2.2.3.
Pour forcer la validation des modifications récentes sur le disque, utilisez les fonctions sync () ou fsync ().
fsync ()synchronise toutes les données et métadonnées du fichier donné avec le périphérique de stockage permanent. Il doit être appelé juste avant la fermeture du fichier correspondant.
sync ()va valider tous les fichiers modifiés sur le disque.