Tout d'abord, ne pas mélanger la bibliothèque standard <stdio.h>
appels (comme fprintf(3)
ou fopen(3)
) avec les appels système (comme open(2)
ou close(2)
ou sync(2)
) que les formateurs sont des routines bibliothèque qui utilisent des tampons en cours de traitement pour stocker les données temporaires , pour lequel le système n'est pas conscient, et les autres sont des interfaces de système d'exploitation qui rendent le système responsable de la maintenance des données à partir de maintenant. Vous les distinguerez facilement car les premiers utilisent les descripteurs FILE *
pour fonctionner, tandis que les derniers utilisent int
descripteurs entiers pour fonctionner.
Donc, si vous utilisez un appel système pour assurer que vos données sont correctement synchronisées sur le disque, il est absolument neccessary au premier fflush(3)
vos processus données tampons avant de faire le système de fichiers ou sync(2)
fsync(2)
appel.
Aucun sync(2)
est justifié de se produire à fclose(3)
ou même close(2)
temps, ou dans le atexit()
callbacks votre processus fait avant exit()
.
Les tampons du système d'exploitation sont retardés en écriture pour des raisons de performance, et close(2)
n'est pas un événement qui déclenche une telle chose. Pensez simplement que de nombreux processus peuvent être en train de lire et d'écrire le même fichier en même temps, et que chaque close(2)
déclenchement d'un flush du système de fichiers pourrait être pénible à réaliser. Le système d'exploitation déclenche ces appels à intervalles réguliers, sur les appels système umount(2)
, sur l'arrêt du système et sur des appels spécifiques aux appels système sync(2)
et fsync(2)
.
Si vous devez maintenir le descripteur FILE *fd
ouvert, juste faire une fflush(fd)
pour ce descripteur pour faire en sorte que le système d'exploitation a tous ses tampons pour fwrite(3)
d ou fprintf(3)
données ées en premier.
Donc finalement, si vous utilisez <stdio.h>
fonctions, tout d'abord faire un fflush()
pour tous les descripteurs FILE *
que vous avez écrit, ou appelez fflush(NULL);
dire stdio de synchroniser tous les descripteurs en un seul appel. Ensuite, faites l'appel sync(2)
ou fsync(2)
pour vous assurer que toutes vos données sont physiquement sur le disque. Pas besoin de fermer quoi que ce soit.
FILE *fd;
...
fflush(fd);
fsync(fileno(fd));
/* here you know that up to the last write(2) or fwrite(3)...
* data is synced to disk */
Par ailleurs, votre approche d'aller /dev/fd/<number>
pour obtenir le descripteur (que vous aviez précédemment) est défectueux pour deux raisons:
Une fois que vous fermez votre descripteur, /dev/fd/<number>
n'est plus le descripteur que vous voulez. Normalement, ça n'existe pas, même. Essayez ceci:
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
int main()
{
int fd;
char fn[] = "/dev/fd/1";
close(1); /* close standard output */
fd = open(fn, O_RDONLY); /* try to reopen from /dev/fd */
if (fd < 0) {
fprintf(stderr,
"%s: %s(errno=%d)\n",
fn,
strerror(errno),
errno);
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
} /* main */
Vous ne pouvez pas obtenir le répertoire dans lequel un fichier ouvert appartient avec seulement le descripteur de fichier. Dans un fichier multiliaison, il peut y avoir des milliers de répertoires qui pointent juste dessus. Il n'y a rien sur l'inode (ou dans la structure de fichier ouverte) qui vous permet d'obtenir le chemin utilisé pour ouvrir ce fichier. Une façon courante d'utiliser des fichiers temporaires est simplement de les créer et de les immédiatement, ainsi personne ne peut l'ouvrir à nouveau. Même si vous conservez le fichier ouvert, vous y avez accès, mais aucun chemin ne le pointe plus.
Merci, mais ce n'est pas une option. Cela rendrait chaque bloc write() pendant un temps relativement long et nous ne pouvons pas nous le permettre. Lorsque le fichier est fermé est un bon moment pour synchroniser. – Arnout