2013-02-15 27 views
5

Tôi đang cố gắng viết chức năng ghi nhật ký C an toàn chỉ và tôi đang gặp một số vấn đề nghiêm trọng với tệp IO. Vì vậy, về cơ bản, tôi bắt đầu với một fopen gọi thú vị cho phép tôi mở nhật ký trong chế độ cập nhật nhị phân:C: Chủ đề Ghi nhật ký an toàn vào một tệp

FILE *log, *start; 
int timeout = 0, error; 

//make file (fails if file exists) 
log = fopen(LOG_FILE, "wx"); 

//Close the file if a new one was created 
if(log) 
    fclose(log); 

//Open file in update mode (it must exist for this) 
log = fopen(LOG_FILE, "rb+"); 

Tiếp theo, tôi khóa các tập tin, kết hợp với một thời gian chờ nếu một thread khóa nó quá lâu:

//Init other file pointer 
start = log; 

//Lock file (with timeout) 
rewind(start); 
error = lockf(fileno(start), F_TLOCK, 0); 
while(error == EACCES || error == EAGAIN) 
{ 
    //sleep for a bit 
    usleep(LOCKED_FILE_RETRY_TIME); 

    //Incremement timeout 
    timeout += LOCKED_FILE_RETRY_TIME; 

    //Check for time out 
    if(timeout > LOCKED_FILE_TIMEOUT) 
    { 
    return; 
    } 

    //Retry the lock operation 
    error = lockf(fileno(start), F_TLOCK, 0); 
} 

và cuối cùng, tôi thêm thông điệp cần thiết để cuối của tập tin, mở khóa và đóng file:

//Print log entry 
fseek(log, 0, SEEK_END); 
fwrite((const void*) log_msg, 1, strlen(log_msg), log); 

//Unlock the block 
rewind(start); 
lockf(fileno(start), F_ULOCK, 0); 

//Close file 
fclose(log); 

Tuy nhiên, nó có vẻ như phần lớn các mớ hỗn độn độ tuổi được ghi đè trong nhật ký, thay vì được thêm vào, gần như là nếu fopen lấy một "ảnh chụp nhanh" của tệp, chờ cho nó được mở khóa và ghi vào nơi kết thúc của tệp nếu quá trình khác không thêm cho nó. Có ai có bất kỳ ý tưởng như thế nào tôi có thể đi về sửa chữa vấn đề này? Là một sang một bên, tôi muốn ở chế độ cập nhật nhị phân vì cuối cùng tôi sẽ thêm một số chức năng cắt tỉa để đảm bảo tệp nhật ký không vượt quá kích thước nhất định và điều này dễ dàng hơn cho tôi khi thực hiện các cuộc gọi fseek R/W chức năng.

Bất kỳ mẹo nào được đánh giá cao. Cảm ơn trước!

+0

Điều gì sẽ xảy ra khi bạn thực hiện với trình gỡ lỗi? – SecurityMatt

+0

Tất cả các thao tác của bạn là 'bắt đầu' trừ' fseek' và 'fwrite'. điều này có được mong đợi không? – Ganesh

+0

@Ganesh, Có, tôi muốn giữ một tệp con trỏ đến đầu tệp và thực hiện tất cả các văn bản của mình với một tệp khác, chỉ trong trường hợp tôi quên thực hiện 'rewind()' trước khi mở khóa hoặc thực hiện một thao tác khác cần con trỏ đến đầu tệp. – SuperTron

Trả lời

5

Bạn không gọi fflush() trên con trỏ tệp trước khi mở khóa. Bằng cách đó, thông điệp tường trình của bạn vẫn nằm trong bộ đệm stdio, được viết ra trong fclose(), tại thời điểm khóa không còn được giữ.

Để khắc phục sự cố, hãy thêm fflush(log) trước thao tác mở khóa hoặc chỉ cần di chuyển fclose(log) trước đó.

+2

Yup, đó là những gì nó được. Cảm ơn! – SuperTron

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