5

我有一个机器人在 Beaglebone Black 上的 PREEMPT-RT 修补 Linux 操作系统上运行具有实时优先级的控制代码。所有代码都是用 C 语言编写的,运行频率为 500Hz。

在运行代码时,我经常注意到几百毫秒范围内的延迟,并且我已经将其跟踪到我编写的数据记录功能。这种延迟导致我的机器人控制失败,因为我有很多取决于实时功能。

代码的相关部分如下。为了清楚起见,我已经削减了很多代码,但如果需要任何内容​​,我会编辑这篇文章。

FILE *file;

int main(int argc, char** argv) {
    file = fopen(logname, "w");

    while (1) {
        /* Control code stuff*/

        logData();

        time_msec = time_msec + controlLoopTime;
    }
}

void logData() {
    if (time_msec - logTimer_msec >= LOG_TIMER) {
        logTimer_msec = time_msec;

        if (!bLogCreated) {
            fprintf(file,
                    "SensorData1 SensorData2 SensorDataN"
                    );
            bLogCreated = TRUE;
        }

        // log data to file
        fprintf(file,

                "%.2f %.2f\n",

                sensorData1, sensorData2, sensorDataN
        );
    }
}

我需要以良好的速率(可能是 100-125Hz)记录来自多个变量(可能是 20-50)的数据。不需要以控制速率(每 2 毫秒)记录数据,但我已将其降低到 12 毫秒,并且每隔几分钟我仍然会看到延迟峰值。

延迟可能是fprintf呼叫的问题。这是 BeagleBone Black、我的代码的限制,还是仅仅是数据记录的性质?

这里问了一个类似的问题,但似乎没有解决我的问题:Finding latency issues (stalls) in Embedded Linux systems

4

1 回答 1

2

使用fprintf是一个巨大的时间消耗,特别是对于 R/T 日志记录。登录二进制并编写一个实用程序以稍后将其打印出来。

代替:

fprintf(file,"%.2f %.2f %.2f",data1,data2,data3);

做:

fwrite(&data1,sizeof(double),1,file);
fwrite(&data2,sizeof(double),1,file);
fwrite(&data3,sizeof(double),1,file);

更好的是:

struct data {
    double data1;
    double data2;
    double data3;
    time_t event_time;
    ...
};

struct data data;

fwrite(&data,sizeof(struct data),1,file);

如果它仍然太慢,请将结构附加到一个环形队列并让一个单独的线程写出条目。

如果磁盘写入跟不上 [now] 二进制数据,请维护环形队列,仅在检测到致命错误时才转储队列


另外,mmap在写入时考虑使用来访问文件。在此处查看我的答案 [with benchmarks]:以最有效的方式逐行阅读*特定于平台的*

于 2016-02-01T23:25:29.753 回答