web-dev-qa-db-fra.com

Différence entre fflush et fsync

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?

44
Adil

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é.

5
Raedwald

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
2
pulse

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.

0
poordeveloper

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.

0
user3428045