我正在尝试编写一个线程安全的 C 日志记录函数,但文件 IO 存在一些严重问题。所以,基本上,我从一个有趣的fopen
调用开始,让我以二进制更新模式打开日志:
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+");
接下来,我锁定文件,如果另一个线程锁定它的时间过长,则合并一个超时:
//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);
}
最后,我将所需的消息添加到文件末尾,解锁并关闭文件:
//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);
但是,似乎大多数消息都在日志中被覆盖,而不是附加,几乎就像fopen
拍摄了文件的“快照”,等待它被解锁,然后写入文件末尾的位置如果另一个过程没有添加到它。有谁知道我该如何解决这个问题?
顺便说一句,我希望处于二进制更新模式,因为我最终将添加一些修剪功能,以确保日志文件不超过特定大小,这对我来说更容易通过工作fseek
调用和 R/W 功能来完成。
任何提示表示赞赏。预先感谢!