2016-09-30 2 views
5

J'ai écrit un programme qui compacte deux petits fichiers dans un seul fichier plus gros. Je lis d'abord les données des fichiers d'entrée, fusionne les données et écrit la sortie dans un fichier temporaire. Une fois cela terminé, je renommer le fichier temporaire au nom de fichier désiré (situé dans la même partition sur le disque). Voici le pseudo code:Vérifie si le contenu du fichier a bien été écrit sur le disque - n'étant pas mis en file d'attente dans le tampon du contrôleur de disque

FILE* fp_1 = fopen("file_1.dat", "r+b"); 
FILE* fp_2 = fopen("file_2.dat", "r+b"); 
FILE* fp_out = fopen("file_tmp.dat", "w+b"); 

// 1. Read data for the key in two files 
const char* data_1 = ...; 
const char* data_2 = ...; 

// 2. Merge data, store in an allocated buffer 

// 3. Write merged buffer to temp file 
fwrite(temp_buff, estimated_size, 1, fp_out); 
fflush(fp_out); 

fclose(fp_1); 
fclose(fp_2); 
fclose(fp_out); 

// Now rename temp file to desired file name 
if(std::rename("file_tmp.dat", "file_out.dat") == 0) 
{ 
    std::remove("file_1.dat"); 
    std::remove("file_2.dat"); 
} 

J'ai testé à plusieurs reprises le programme avec deux fichiers d'entrée de 5 Mo chacun. Une fois, j'ai soudainement éteint le système en débranchant le câble d'alimentation. Après avoir redémarré le système, j'ai vérifié les données et trouvé que les fichiers d'entrée ont été supprimés et le file_out.dat a été rempli avec tous les zéros. Cela m'a fait croire que le système est tombé juste après que 2 fichiers d'entrée ont été supprimés et les données de sortie étaient encore quelque part dans le tampon du contrôleur de disque. Si cela est vrai, alors est-il possible de vérifier si les données ont réellement été écrites sur le disque?

+1

Voyant que le système d'exploitation ne sait même pas avec certitude (le disque a probablement son propre cache RAM) c'est un problème épineux. – user4581301

Répondre

5

Pas dans le cas général. Le disque peut mentir à l'OS, affirmant que l'écriture est terminée quand elle est juste mise en file d'attente dans le cache RAM embarqué du disque dur, qui sera perdue en cas de coupure de courant soudaine.

Le mieux que vous pouvez faire est de demander explicitement le système d'exploitation de dire le disque « vraiment, vraiment synchroniser tout » après avoir effectué la fflush, soit portée limitée avec fsync ou en utilisant quelque chose comme sync or syncfs (les anciens fichiers synchronisations tous systèmes, ce dernier limite la portée au système de fichiers correspondant à un seul descripteur de fichier). Vous voulez faire une cible fsync après la finale fflush mais avant la rename, et/ou un plus large sync/syncfs après la rename mais avant que les remove appels afin que les données et les tables de système de fichiers est définitivement mis à jour avant de supprimer les fichiers source .

Bien sûr, comme je l'ai dit, c'est tout le meilleur effort; Si le contrôleur de disque ment au système d'exploitation, il n'y a rien que vous pouvez faire pour écrire de nouveaux micrologiciels et pilotes pour le disque, ce qui va probablement trop loin.