2

我有这个问题,但有些人要求提供更多信息。所以我提供更多信息。

我有一张智能卡和一个读卡器。用户可以随时从读卡器中取出卡片。智能卡有不同的块(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。有什么方法可以解决这个问题?

附言。尽管我需要检查一下,但可能无法使用单个提交来编写所有内容。

pps。现在我想起来了,如果说第 12 步成功,但第 15 步抛出异常或返回 false,我想我可能会遇到类似的问题。在这种情况下该怎么办?

我非常感谢周到和仔细的回答。谢谢你。

4

3 回答 3

1
Do steps 15, 16 and 17 before the 10 and 12 steps.

什么不应该工作。换线就行了。你认为它会起作用吗?

如果你不喜欢那样。您可以为状态保留一点。开始过程时将其设置为 1,完成后将其设置为零。

下次,您可以检查该位并减少信用,然后再继续该过程。

于 2013-09-30T17:15:38.070 回答
1

考虑使用提交日志,这是许多文件系统和数据库服务器使用的一种机制,即使在意外断电、系统崩溃或设备连接失败的情况下也能确保数据完整性。

提交日志的基本思想是,在将数据写入实际块之前,先写下将要写入其他块的内容。然后,如果写操作被中断,您可以查看提交日志并重播被中断的完整写操作。这将使数据恢复到一致的状态。

在卡片上为此指定 N+1 个块,其中 N 是您要更改的块数。在这种情况下,看起来您正在更改五个块,因此您需要在日志中使用六个。第六个块是“状态”,表示实际写入是否未完成。

例如,您可以像这样布置六个日志块:

Journal block: |  0  |  1  |  2  |  3  |  4  |   5   |
Contents:      | B10 | B12 | B15 | B16 | B17 | STATE |

状态块可以指示“脏”或“干净”。您对这些状态使用哪些值并不重要。(例如,您可以使用 true 或 false。我建议将它们设为编译时常量JOURNAL_STATE_DIRTYJOURNAL_STATE_CLEAN这样它们的含义就很清楚了。)

当卡片被格式化时,状态块应该被初始化为“clean”。

操作的基本顺序如下:

  1. 将新数据写入五个日志块。
  2. 将状态块设置为脏。
  3. 将新数据写入实际目标块(10、12、15、16、17)。
  4. 将状态块设置为清洁。

初始化卡时,您要做的第一件事就是检查状态是否为脏。如果是,则通过在步骤 3 中恢复写入操作来重放日志,除非在这种情况下,您正在从日志块中读取“新数据”。

如果操作在第 2 步完成之前被中断,状态块应该是“干净的”并且不会执行日志重放。写入将完全失败,卡将包含完整完整的旧数据。

如果在第 2 步完成后操作被中断,则状态块将为“脏”,并且下次连接设备时将重播日志。实际的块 10、12、15、16 和 17 可能已损坏,但重放日志将纠正此问题,结果是在重放日志后块将具有正确的新值。

请注意,只有使用该卡的所有软件都理解并实现了这种日志技术,这种方法才会有效。 如果用户在写入过程中移除卡并将其带到不了解日志的设备,它将使用损坏的数据。这是你无能为力的。

如果您想更加偏执,请将另一个块专用于将包含五个数据块的校验和的日志。这将允许您在重播步骤期间检测日志数据是否损坏。在这种情况下,您可能会通知用户他们的卡已损坏,他们需要对其进行维修。

于 2013-09-30T17:59:16.583 回答
0

你应该实现一个循环缓冲区

数据结构将包含一个 bool 值,因此在完成指令集后,您可以在结束处理之前将 valid 设置为 true,然后function 在每次写入时循环通过缓冲区,以便检测未完成的访问

于 2013-09-30T17:43:18.807 回答