我有这个问题,但有些人要求提供更多信息。所以我提供了更多信息。
我有智能卡和读卡器。用户可以随时从读卡器中取出卡片。 智能卡有不同的块(16字节),我可以写任何我想要的块。
现在我有这个以线程运行的功能:
3 void function (void *p)
4 {
5 if(smartCardRemoved)
6 doSmth();
7 else
8 {
9 // Smart card is inside the reader
10 writeDataToCard(handle, blockNr, data1);
11 blockNr++;
12 writeDataToCard(handle, blockNr, data2);
13 blockNr=12;
14 readDataFromCard(blockNr, credit);
15 credit--;
16 writeDataToCard(cardHandle, blockNr, credit);
}
}
data1
和data2
基本上是时间戳,credit
是信用卡。
现在的问题是。说执行步骤10和12,意味着时间戳
写到卡上。但现在,用户从读卡器中取出卡
- 这意味着步骤14,15,16将不会被执行 - 这对我来说是个问题
因为时间戳是写的,但信用没有减少。正如我所说
是个问题。因此,如果执行步骤10和12,则还必须执行步骤14,15和16。有什么方法可以解决这个问题?
PS。虽然我需要检查,但可能无法使用单个提交编写所有内容。
PPS。现在我想起来了,如果说第12步成功,我认为可能有类似的问题,但是第15步抛出异常或返回false。在这种情况下该怎么办?
我真的很感激周到细致的回答。谢谢。
答案 0 :(得分:1)
Do steps 15, 16 and 17 before the 10 and 12 steps.
什么不该起作用。只需交换线路。你觉得它会起作用吗?
如果你不喜欢那样。你可以保留一点状态。在您开始流程时将其设置为一个,并在完成时将其设置为零。
下次,您可以检查该位并减少积分,然后再继续此过程。
答案 1 :(得分:1)
考虑使用提交日志,这是许多文件系统和数据库服务器使用的机制,即使面对意外断电,系统崩溃或设备连接故障,也能确保数据完整性。
提交日志的基本思想是,在将数据写入实际块之前,将要写入的内容写入其他块。然后,如果写入操作被中断,您可以查看提交日志并重放中断的完整写入操作。这将使数据恢复到一致状态。
在卡上为此添加N + 1个块,其中N是您要更改的块数。在这种情况下看起来你正在改变五个街区,所以你需要六个日记。第六个块是“状态”,表示实际写入是否不完整。
例如,您可以像这样布置六个日志块:
Journal block: | 0 | 1 | 2 | 3 | 4 | 5 |
Contents: | B10 | B12 | B15 | B16 | B17 | STATE |
状态块可以表示“脏”或“干净”。您用于这些状态的值并不重要。 (例如,您可以使用true或false。我建议将它们设置为JOURNAL_STATE_DIRTY
和JOURNAL_STATE_CLEAN
等编译时常量,以便它们的含义清晰。)
格式化卡时,应将状态块初始化为“清理”。
基本操作顺序如下:
初始化卡时,您要做的第一件事就是检查状态是否脏。如果是,则通过在步骤3恢复写入操作来重放日志,除非在这种情况下,您正在从日志块中读取“新数据”。
如果在步骤2完成之前操作被中断,则状态块应该是“干净的”并且不会执行日志重放。写入将完全失败,卡将包含旧数据,完整无缺。
如果在步骤2完成后操作中断,则状态块将“脏”,并且下次连接设备时将重播日志。实际的块10,12,15,16和17可能已损坏,但重播日志将更正此问题,结果是在重放日志后块将具有正确的新值。
请注意,只有使用该卡的所有软件都能理解并实施此日志技术时,此方法才能正常工作。如果用户在写入中删除卡并将其带到不具有此功能的设备上了解该期刊,它将使用损坏的数据。你无能为力。
如果你想要超偏执,请将另一个块专用于包含五个数据块校验和的日志。这将允许您在重播步骤中检测日志数据是否已损坏。在这种情况下,您可能会通知用户他们的卡已损坏,他们需要为其提供服务。
答案 2 :(得分:0)
你应该实现一个循环缓冲区
数据结构将包含bool值,因此在完成指令集后,您可以在离开处理function
之前将有效值设置为true。
并在每次写入时循环缓冲区,以便检测未完成的访问