2016-09-30 30 views
5

Napisałem program, który kompaktuje dwa małe pliki do jednego większego pliku. Najpierw odczytałem dane z plików wejściowych, scaliłem dane i zapisałem dane wyjściowe do pliku tymczasowego. Po zakończeniu zmieniam nazwę pliku tymczasowego na żądaną nazwę pliku (znajdującą się w tej samej partycji na dysku). Oto pseudo kod:Sprawdź, czy zawartość pliku została faktycznie zapisana na dysku - nie jest w kolejce w buforze kontrolera dysku

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"); 
} 

Wielokrotnie testowałem program z dwoma plikami wejściowymi po 5 MB każdy. Jednorazowo nagle zamknąłem system, odłączając kabel zasilający. Po ponownym uruchomieniu systemu sprawdziłem dane i odkryłem, że pliki wejściowe zostały usunięte, a file_out.dat wypełnione zerami. To sprawiło, że uwierzyłem, że system spadł zaraz po usunięciu 2 plików wejściowych, a dane wyjściowe wciąż znajdowały się gdzieś w buforze kontrolera dysku. Jeśli to prawda, czy jest jakiś sposób, aby sprawdzić, czy dane rzeczywiście zostały zapisane na dysku?

+1

Widząc, że system operacyjny nawet nie wie na pewno (dysk prawdopodobnie ma własną pamięć podręczną RAM), jest to drażliwy problem. – user4581301

Odpowiedz

5

Nie w ogólnym przypadku. Dysk może spoczywać na systemie operacyjnym, twierdząc, że zapis zakończył się, gdy jest on rzeczywiście umieszczony w kolejce w pamięci podręcznej RAM dysku twardego, która zostanie utracona w przypadku nagłej utraty zasilania.

Najlepsze co możesz zrobić, to wyraźnie poprosić OS powiedzieć dysk do „naprawdę synchronizacji wszystko” po tym, jak wykonał fflush albo ograniczony zakres korzystania z fsync lub coś podobnego sync or syncfs (dawny synchronizacji wszystkich plików systemy te ostatnie ograniczają zakres do systemu plików odpowiadającego pojedynczemu deskryptorowi pliku). którą chcesz zrobić ukierunkowanego fsync po ostatecznym fflush ale przed rename i/lub szersze sync/syncfs po rename ale przed połączeniami remove więc dane i tabele system plików jest zdecydowanie zaktualizowany przed usunięciem plików źródłowych .

Oczywiście, jak powiedziałem, to wszystko, co najlepsze; jeśli kontroler dysku leży w systemie operacyjnym, nic nie da się zrobić, pisząc nowe oprogramowanie układowe i sterowniki dysku, co prawdopodobnie posuwa się za daleko.