2016-09-30 11 views
5

Tôi đã viết một chương trình nén hai tệp nhỏ thành một tệp lớn hơn. Lần đầu tiên tôi đọc dữ liệu từ các tệp đầu vào, hợp nhất dữ liệu và ghi đầu ra vào tệp tạm thời. Một khi điều này hoàn thành, tôi đổi tên file tạm thời thành tên file mong muốn (nằm trong cùng một phân vùng trên đĩa). Đây là mã giả:Kiểm tra xem nội dung tệp đã thực sự được ghi vào đĩa chưa được xếp hàng trong bộ đệm của bộ điều khiển đĩa

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

Tôi liên tục kiểm tra chương trình với hai tệp đầu vào là 5 MB mỗi. Một lần tôi đột nhiên tắt hệ thống bằng cách rút cáp nguồn. Sau khi khởi động lại hệ thống, tôi đã kiểm tra dữ liệu và thấy rằng các tệp đầu vào đã bị xóa và file_out.dat được lấp đầy bằng tất cả các số không. Điều này làm cho tôi tin rằng hệ thống đã đi xuống ngay sau khi 2 tập tin đầu vào đã được gỡ bỏ và dữ liệu đầu ra vẫn còn ở đâu đó trong bộ đệm của bộ điều khiển đĩa. Nếu điều này là đúng, thì có cách nào mà tôi có thể kiểm tra xem dữ liệu đã thực sự được ghi vào đĩa không?

+1

Xem như hệ điều hành thậm chí không biết chắc chắn (đĩa có thể có bộ đệm RAM riêng của nó) đây là một vấn đề gai góc. – user4581301

Trả lời

5

Không có trong trường hợp chung. Đĩa này có thể nằm trên hệ điều hành, cho phép ghi hoàn thành khi nó thực sự được xếp hàng đợi trong bộ đệm RAM trên ổ đĩa cứng, sẽ bị mất khi mất điện đột ngột. Điều tốt nhất bạn có thể làm là yêu cầu hệ điều hành yêu cầu đĩa “thực sự, thực sự đồng bộ hóa mọi thứ” sau khi bạn đã thực hiện fflush, hoặc phạm vi giới hạn với fsync hoặc sử dụng một cái gì đó như sync or syncfs (trước đây đồng bộ tất cả tệp hệ thống, sau này giới hạn phạm vi cho hệ thống tệp tương ứng với một bộ mô tả tệp đơn). Bạn muốn thực hiện nhắm mục tiêu fsync sau fflush cuối cùng nhưng trước rename và/hoặc sync/syncfs lớn hơn sau rename nhưng trước khi gọi remove để bảng dữ liệu và tệp hệ thống được cập nhật chắc chắn trước khi bạn xóa các tệp nguồn .

Tất nhiên, như tôi đã nói, đây là tất cả nỗ lực tốt nhất; nếu bộ điều khiển đĩa nằm trên hệ điều hành, không có gì bạn có thể làm nhút nhát bằng việc viết chương trình cơ sở và trình điều khiển mới cho đĩa, điều này có lẽ sẽ đi quá xa.

Các vấn đề liên quan