【问题标题】:Ring Buffer with time stamp带时间戳的环形缓冲区
【发布时间】:2018-08-16 10:56:59
【问题描述】:

我需要一个环形缓冲区(C 语言),它可以在运行时保存任何类型的对象(几乎数据将是不同的信号值,如电流(100 毫秒和 10 毫秒)和温度等)(我我不确定它是否必须是固定大小)并且它需要非常高性能。尽管它处于多任务嵌入式环境中。

实际上我需要这个缓冲区作为备份,这意味着嵌入式软件将正常工作并将数据保存到环形缓冲区中,到目前为止,无论出于何种原因,当发生错误时,我可以参考测量值然后我将能够查看它们并确定问题。另外我需要在环形缓冲区上做一个时间戳,这意味着存储在环形缓冲区上的每个数据(信号值)都将与测量的时间一起存储。

任何代码或想法将不胜感激。一些需要的操作是:

创建一个特定大小的环形缓冲区。 将其与整个软件链接。 放在尾部。 从头上得到。 出错时,读取数据及其发生时间(时间戳)。 返回计数。 缓冲区满时覆盖。

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

typedef struct ring_buffer
{
     void * buffer;      // data buffer
     void * buffer_end;  // end of data buffer
     void * data_start;  // pointer to head
     void * data_end;    // pointer to tail
     uint64_t capacity;  // maximum number of items in buffer
     uint64_t count;     // number of items in the buffer
     uint64_t size;      // size of each item in the buffer
 } ring_buffer;

 void rb_init (ring_buffer *rb, uint64_t size, uint64_t capacity )
 {
     rb->buffer = malloc(capacity * size);
         if(rb->buffer == NULL)
             // handle error
         rb->buffer_end = (char *)rb->buffer + capacity * size;
         rb->capacity = capacity;
         rb->count = 0;
         rb->size = size;
         rb->data_start = rb->buffer;
         rb->data_end = rb->buffer;
 }

 void cb_free(ring_buffer *rb)
 {
     free(rb->buffer);
     // clear out other fields too, just to be safe
 }

 void rb_push_back(ring_buffer *rb, const void *item)
 {
     if(rb->count == rb->capacity){
         // handle error
     }
     memcpy(rb->data_start, item, rb->size);
     rb->data_start = (char*)rb->data_start + rb->size;
     if(rb->data_start == rb->buffer_end)
         rb->data_start = rb->buffer;
     rb->count++;
 }

 void rb_pop_front(ring_buffer *rb, void *item)
 {
     if(rb->count == 0){
         // handle error
     }
     memcpy(item, rb->data_end, rb->size);
     rb->data_end = (char*)rb->data_end + rb->size;
     if(rb->data_end == rb->buffer_end)
         rb->data_end = rb->buffer;
     rb->count--;
 }

【问题讨论】:

  • "current (100ms and 10ms)" 这是什么意思?
  • 这意味着,例如,在运行时将读取两个不同的电流信号,一个每 10 毫秒读取一次,另一个在 100 毫秒读取一次
  • @AlexF 在资源受限的嵌入式系统中制作泛型类型的硬拷贝是个坏主意,不要那样做。它会使程序膨胀很多。
  • @AlexF 为什么在这样的系统上你甚至会有多种类型,以至于你需要实现通用 ADT?早在我看到一行代码之前,这就是主要的代码气味。
  • @Lundin 程序太长了,没错

标签: c


【解决方案1】:

使用通用类型的硬拷贝创建环形缓冲区/FIFO 对于嵌入式系统来说是非常值得怀疑的设计。对于如此接近硬件的代码,您不应该需要如此高级别的抽象。

要么创建一个带有数据类型标记(如枚举)的环形缓冲区,外加一个void* 来分配其他地方的数据,要么创建一个所有数据都属于同一类型的环形缓冲区。其他一切很可能是混淆程序设计(“XY 问题”)。

您需要一些方法在内部锁定对环形缓冲区的访问,以使其成为线程安全/中断安全的。这和时间戳一样,必须由环形缓冲区 ADT 在内部处理。

【讨论】:

  • 用通用类型的硬拷贝创建一个环形缓冲区/FIFO对于嵌入式系统来说是非常有问题的设计。对于如此接近硬件的代码,您不应该需要那么高的抽象级别。我无法理解。你能帮我解释一下吗!
  • @Khaled 你想建立一个错误跟踪系统。所以保存一个错误号。无需将整个程序拖入环形缓冲区本身即可查看出错的地方。如果您需要保存其他信息,请使用错误号 + 空指针。
猜你喜欢
  • 2012-04-04
  • 2019-07-05
  • 1970-01-01
  • 2018-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多