在循环缓冲区中查找最旧的条目,考虑整数溢出

时间:2013-09-09 11:29:51

标签: logging embedded circular-buffer flash-memory

我想将一系列日志条目存储在闪存设备的循环缓冲区中。

闪存设备没有板载磨损均衡,所以我需要在我的记录代码中处理它。循环缓冲区将作为实现的一部分执行此操作,但我遇到整数溢出问题。

我打算将闪存区划分为以下区域:

char index;
char checksum;
char logdata[512-(sizeof(char)*2))];

索引= 0xFF表示“已擦除”。因此ID的范围可以从0x00到0xFE(零到254)。这意味着增量规则是:

id = (last_id + 1) % 255

当闪存开始时,它看起来像这样(仅显示ID):

FF FF FF FF FF

我们选择第一个空块(索引零)并在第一个日志条目中写入:

00 FF FF FF FF

这一直持续到没有条目被删除:

00 01 02 03 04

当我们选择编号最小的块时,将其擦除并用新数据覆盖:

05 01 02 03 04

但是当8位ID溢出时,会发生不好的事情:

FA FB FC FD FE
00 FB FC FD FE  (OK)
01 FB FC FD FE  (Not OK - should have overwritten "FB"!)
02 FB FC FD FE  (Stuck writing the first block over and over)

这意味着第一个块现在用于每次写入,我们又回到了我想避免的“不均匀写入”场景中。我想要做的是找到最旧的块,在这种情况下是“FB”。

这是我目前的代码(在Python中):

buf = [0xFF]*5

for i in range(260):
    note = ""

    slot = None

    # Find first erased slot
    for x in range(len(buf)):
        if buf[x] == 0xFF:
            slot = x
            break

    if slot is None:
        # No erased slots, find lowest numbered slot
        n = 0xFF
        for x in range(len(buf)):
            if buf[x] < n:
                n = buf[x]
                slot = x

    # Debug output
    print ''.join(["%02X " % x for x in buf])

    # Write new block
    buf[slot] = i % 255

如何正确处理整数溢出情况?

2 个答案:

答案 0 :(得分:0)

该循环正在找到编号最小的插槽。 00,01和02都比FB少。这就是为什么第一个插槽在第一次翻转后一直重复使用的原因。

您需要更好的设计。也许保留一个循环缓冲区索引,它始终引用下一个可用的槽。

答案 1 :(得分:0)

我看到了两种可能的方法。

第一个保留队列的相同容量,但要求容量必须小于255。

这个想法是完全按照你现在的方式编写,但是,不是寻找最低的数字,而是先查找序列中的不连续性,即从一个单元格到接下来不是一个。初步了解情况:

FA FB FC FD FE
00 FB FC FD FE  (discontinuous at fe->fa, use fa)
00 01 FC FD FE  (discontinuous at 00->fb, use fb)
00 01 02 FD FE  (discontinuous at 01->fc, use fc)

它需要小于255的原因是,一旦它变大, 没有不连续性,因为数字将在每个周期完全包围一次。

另一种方法是简单地使用特殊标记ff来指示下一个空闲时段,无论如何。

这种方法的工作方式是,无论何时向条目写入记录,您还可以使用ff标记写下一个条目。

然后,要查找要填充的下一个条目,只需查找第一个ff即可。在启动阶段,会有多个ff标记,您只需选择第一个,但一旦用尽,每次写入都会给您另一个:

ff ff ff ff ff ff
00 ff ff ff ff ff
00 01 ff ff ff ff
00 01 02 ff ff ff
00 01 02 03 ff ff
00 01 02 03 04 ff
ff 01 02 03 04 05
06 ff 02 03 04 05

这会将循环缓冲区容量减少一个,导致读取次数是原始方案的两倍,因此我更倾向于使用上面的第一个方案来进行最少的写入。

但是,如果你想要更大的缓冲区(大于254个元素),这是实现它的一种方法。