我想将一系列日志条目存储在闪存设备的循环缓冲区中。
闪存设备没有板载磨损均衡,所以我需要在我的记录代码中处理它。循环缓冲区将作为实现的一部分执行此操作,但我遇到整数溢出问题。
我打算将闪存区划分为以下区域:
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
如何正确处理整数溢出情况?
答案 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个元素),这是实现它的一种方法。