5

我正在尝试编写一个线程安全的 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 功能来完成。

任何提示表示赞赏。预先感谢!

4

1 回答 1

5

您在解锁之前没有调用fflush()文件指针。fclose()这样,您的日志消息将保留在 stdio 缓冲区中,以便在不再持有锁时写出。

要解决此问题,fflush(log)请在解锁操作之前添加一个,或者只是将其移动到fclose(log)它之前。

于 2013-02-15T21:28:50.907 回答