【问题标题】:Real-time write to file, C实时写入文件,C
【发布时间】:2021-09-17 00:19:10
【问题描述】:

我正在尝试构建一个文件,我将在其中保留应用程序中最重要的事件。我构建了一个负责记录的函数,但它似乎没有按预期工作。首先,在无限while() 循环期间,APPLOG.LOG 文件中不会出现消息,但仅在应用程序完成时才会出现。我应该如何构建将信息实时写入文件的功能? 我使用了很多 *.c 文件,并且我希望能够在每个文件中记录事件。 fLog = fopen(LOG_FILENAME, "w"); 不应该在 APLOG(...) 函数内吗? 下面是一些负责记录的代码。

日志记录.h

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>

#define TYPE_GENERAL                1
#define TYPE_BINARY                 2
#define TYPE_INFO                   3
#define TYPE_WARNING                4
#define TYPE_ERROR                  5

#define LOG_FILENAME                "APPLOG.LOG"

FILE *fLog;

logging.c

void APLOG(FILE *fLog, uint32_t type, char *MESSAGE)
{    
    if(fLog == NULL)
    {
        printf("Error open %s FILE!", TRLOG_FILENAME);   
        exit(1);             
    }
    else
    {
        switch(type)
        {
            case TYPE_GENERAL:
                fprintf(fLog, "%s %s %s: %s \n",__DATE__, __TIME__, "GENERAL", MESSAGE);
                break;
            case TYPE_BINARY:
                fprintf(fLog, "%s %s %s: %s \n",__DATE__, __TIME__, "BINARY", "ATTEMPTED TO WRITE A BINARY MESSAGE. FUNCTION NOT ACTIVE");
                break;
            case TYPE_INFO:
                fprintf(fLog, "%s %s %s: %s \n",__DATE__, __TIME__, "INFO", MESSAGE);
                break;
            case TYPE_WARNING:
                fprintf(fLog, "%s %s %s: %s \n",__DATE__, __TIME__, "WARINNG", MESSAGE);
                //send warning to external app
                break;
            case TYPE_ERROR:
                fprintf(fLog, "%s %s %s: %s \n",__DATE__, __TIME__, "ERROR", MESSAGE);
                //send raport to app provider
                break;
            default:
                break;
        }
    }
}

main.c

int main(int argc, char **argv)
{
    fLog = fopen(LOG_FILENAME, "w");
    
    APLOG(fLog, TYPE_INFO, "APP HAS BEEN RUNNING. LOGGING STARTED" );

    while()
    {
        //endless while here. If any part of the code does not work, exit the while and report the problem. More APLOG here.
    }

    APLOG(fLog, TYPE_ERROR, "OUT OF WORK. BACK TO EMERGENCY."); 
    return 0;   
}

【问题讨论】:

  • 您知道基于FILE * 的IO 被缓冲了吗?你试过fflush()吗?
  • __DATE__, __TIME__ 这将在日志文件的每一行打印文件编译的相同日期和时间。您想获取 current 日期和时间,不是吗? Shouldn'tfLog = fopen(LOG_FILENAME, "w"); be inside the APLOG(...) function?想要它在那里吗?答案取决于希望你的函数具有什么语义。
  • "fLog = fopen(LOG_FILENAME, "w"); 不应该在APLOG(...) 函数中吗?"不,因为该文件会随着每条记录的消息而被销毁和重写。如果在函数内,文件应该以"a" 模式打开。

标签: c linux file


【解决方案1】:

FILE * 是一个流,这意味着写入文件是缓冲的,并且在系统最方便时实际写入数据(以最大限度地提高性能)。

您可以更直接地使用不使用流的一组函数来执行此操作:open/close/write/read/... 但即使使用这些函数,写入也会被缓冲。

通过“流式”访问文件(fopen/fprintf/fclose/...),有一种方法可以将所有等待写入的数据实际写入磁盘。这就是函数 fflush

如果您希望您的应用程序实际上一直刷新其缓冲区,您必须在 APLOG 结束时使用 fflush(fLog);,这样每个 fprintf 后面都会跟着一个 fflush... p>

【讨论】:

  • "但即使使用这些函数,写入也会被缓冲。"在这种情况下有点误导。至少有 2 个缓冲区,其中一个在程序中由 FILE * 流使用,write()/read() 函数不使用。并且有一个磁盘驱动程序缓冲区,它会影响这两种变体并且不会被fflush() 刷新。但是其他应用程序仍然可以读取新数据,即使磁盘驱动程序仍在缓冲它。
  • 或者换句话说:使用函数write(),在每个fwrite()/fprintf()/...之后立即使用fflush(),或者使用setvbuf()禁用FILE *流缓冲区和_IONBF 在缓冲写入数据时都具有相同的行为。要刷新到磁盘,请使用 fsync()
猜你喜欢
  • 1970-01-01
  • 2019-06-05
  • 1970-01-01
  • 2012-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-06
相关资源
最近更新 更多