本申请属于数据处理技术领域,尤其涉及一种基于nandflash的数据存储方法、终端设备及计算机可读存储介质。
背景技术:
在金融支付设备中,通常需要安全的存储多个密钥,这些密钥往往以密文的形式存储在基于flash的文件系统中,并且这些密钥还会定期或不定期的更新。
然而,在实际应用中,flash文件系统需要为众多文件的访问服务,密钥写入的速度较慢,并且flash文件系统开销较大,若金融支付设备内存资源不充足的时候,就会无法支持文件系统。
技术实现要素:
有鉴于此,本申请实施例提供了一种基于nandflash的数据存储方法、终端设备及计算机可读存储介质,以解决目前数据的存储写入速度慢、内存开销大的问题。
本申请实施例的第一方面提供了一种基于nandflash的数据存储方法,应用于终端设备,所述方法包括:
获取分配的存储空间,所述存储空间包括至少两个存储块,每个存储块包括至少两个存储页,每个存储页的大小相等;
将获取的每条待存储数据依次写入所述存储空间的存储页中,所述存储空间中写入的数据形成数据队列;
基于所述存储空间中写入的数据队列进行数据处理,所述数据处理包括:循环追加写入处理、标记式删除处理、开机检索整理处理、缓冲索引读取处理。
本申请实施例的第二方面提供了一种终端设备,包括:
获取模块,用于获取分配的存储空间,所述存储空间包括至少两个存储块,每个存储块包括至少两个存储页,每个存储页的大小相等;
存储模块,用于将获取的每条待存储数据依次写入所述存储空间的存储页中,所述存储空间中写入的数据形成数据队列;
处理模块,用于基于所述存储空间中写入的数据队列进行数据处理,所述数据处理包括:循环追加写入处理、标记式删除处理、开机检索整理处理、缓冲索引读取处理。
本申请实施例的第三方面提供了一种终端设备,包括存储器、处理器以及存储在所述存储器中并可在所述处理器上运行的计算机程序,所述处理器执行所述计算机程序时实现本申请实施例第一方面提供的所述方法的步骤。
本申请实施例的第四方面提供了一种计算机可读存储介质,所述计算机可读存储介质存储有计算机程序,所述计算机程序被一个或多个处理器执行时实现本申请实施例第一方面提供的所述方法的步骤。
本申请实施例的第五方面提供了一种计算机程序产品,所述计算机程序产品包括计算机程序,所述计算机程序被一个或多个处理器执行时实现本申请实施例第一方面提供的所述方法的步骤。
本申请实施例是在flash存储空间中分配一段存储空间专门用于存储特定的数据,首先需要获取分配的存储空间,存储中间中包括多个存储块,每个存储块又包括了多个存储页,每个存储页大小相等,然后将获取的每条待存储数据依次写入所述存储空间的存储页中,存储空间中存储的数据会形成数据队列,可以对所述数据队列进行相关的数据处理,由于这一段存储空间是专门分配用于存储特定的数据,所以,不会产生众多文件的访问服务、因为能够提高数据的写入速度,而且,存储空间的大小有限,不会造成过大的内存开销。
附图说明
为了更清楚地说明本申请实施例中的技术方案,下面将对实施例或现有技术描述中所需要使用的附图作简单地介绍,显而易见地,下面描述中的附图仅仅是本申请的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动性的前提下,还可以根据这些附图获得其他的附图。
图1是本申请实施例提供的一种基于nandflash的数据存储方法的实现流程示意图;
图2是本申请实施例提供的一种循环追加写入处理方法的实现流程示意图;
图3是本申请实施例提供的一种标记式删除处理方法的实现流程示意图;
图4是本申请实施例提供的一种开机检索整理处理方法的实现流程示意图;
图5是本申请实施例提供的一种终端设备的示意框图;
图6是本申请实施例提供的另一种终端设备的示意框图。
具体实施方式
以下描述中,为了说明而不是为了限定,提出了诸如特定系统结构、技术之类的具体细节,以便透彻理解本申请实施例。然而,本领域的技术人员应当清楚,在没有这些具体细节的其它实施例中也可以实现本申请。在其它情况中,省略对众所周知的系统、装置、电路以及方法的详细说明,以免不必要的细节妨碍本申请的描述。
应当理解,当在本说明书和所附权利要求书中使用时,术语“包括”指示所描述特征、整体、步骤、操作、元素和/或组件的存在,但并不排除一个或多个其它特征、整体、步骤、操作、元素、组件和/或其集合的存在或添加。
还应当理解,在此本申请说明书中所使用的术语仅仅是出于描述特定实施例的目的而并不意在限制本申请。如在本申请说明书和所附权利要求书中所使用的那样,除非上下文清楚地指明其它情况,否则单数形式的“一”、“一个”及“该”意在包括复数形式。
还应当进一步理解,在本申请说明书和所附权利要求书中使用的术语“和/或”是指相关联列出的项中的一个或多个的任何组合以及所有可能组合,并且包括这些组合。
如在本说明书和所附权利要求书中所使用的那样,术语“如果”可以依据上下文被解释为“当...时”或“一旦”或“响应于确定”或“响应于检测到”。类似地,短语“如果确定”或“如果检测到[所描述条件或事件]”可以依据上下文被解释为意指“一旦确定”或“响应于确定”或“一旦检测到[所描述条件或事件]”或“响应于检测到[所描述条件或事件]”。
为了说明本申请所述的技术方案,下面通过具体实施例来进行说明。
图1是本申请实施例提供的一种基于nandflash的数据存储方法的实现流程示意图,应用于终端设备,如图所示该方法可以包括以下步骤:
步骤s101,获取分配的存储空间,所述存储空间包括至少两个存储块,每个存储块包括至少两个存储页,每个存储页的大小相等。
在本申请实施例中,所述存储空间可以是nandflash中的一段存储空间,flash是一种固态、电可擦除可写入、掉电不丢失信息的计算机存储介质,按实现结构,flash分为norflash和nandflash两种,其中,nandflash是指以“与非门”为存储单元结构的flash。本方案是针对nandflash的实施方案。nandflash的特点是:由多个存储块组成,而每个存储块又均由相同数目的存储页组成,每个存储页由数据区和冗余区组成,所述数据区用于存储当前写入的数据;所述冗余区包括用于标记坏块的坏块标记和用于校验数据区的数据正确性的ecc码。每个存储页大小为相同数目的若干字节;以存储页为单位读写数据;只能以存储块为单位进行擦除,存储块只有被擦除后才能写入任意的新数据;不可以对同一存储页进行多于一次的写入;容易出现比特位翻转和坏块,所谓坏块,是指该存储块里面存在一个或几个位元经擦除后仍为0的情况。本申请实施例中分配的存储空间为一段独立的、物理地址连续的nandflash存储空间,作为数据的存储载体。
步骤s102,将获取的每条待存储数据依次写入所述存储空间的存储页中,所述存储空间中写入的数据形成数据队列。
在本申请实施例中,所述数据可以是密钥记录,相应的,所述终端设备可以是金融支付设备。每条待存储数据可以是每条密钥记录,本申请实施例后续以密钥记录作为数据进行举例。
作为本申请又一实施例,所述将获取的每条待存储数据依次写入所述存储空间的存储页中包括:
在接收到存储第一条待存储数据的指令后,将第一条待存储数据写入所述存储空间的有效存储页中,所述有效存储页为非坏存储块中的存储页;
在接收到存储第n条待存储数据的指令后,将第n条待存储数据写入所述数据队列的队尾的下一个有效存储页,其中,n为大于1的自然数,当所述数据队列的队尾在所述存储空间的最后一个有效存储页时,所述数据队列的队尾的下一个有效存储页为所述存储空间的第一个有效存储页。
在本申请实施例中,所述有效存储页为非坏存储块中的存储页。实际上每次进行存储密钥记录时,将待存储(新增或待更新)的密钥记录紧跟地填写在上次写入的最后一个存储页的下一个有效存储页。若上一个存储的存储页(队尾所在的存储页)位于所分配存储空间的最后一个有效存储页,则当前待写入存储页回绕到所分配存储空间的第一个有效存储页。
步骤s103,基于所述存储空间中写入的数据队列进行数据处理,所述数据处理包括:循环追加写入处理、标记式删除处理、开机检索整理处理、缓冲索引读取处理。
在本申请实施例中,对存储在存储空间的数据队列可以进行数据处理,例如,写入操作、删除操作、读取操作等,本申请实施例中,可以进行循环追加写入处理、标记式删除处理、开机检索整理处理、缓冲索引读取处理。下面分别通过不同的实施例描述循环追加写入处理、标记式删除处理、开机检索整理处理、缓冲索引读取处理。
由于本申请实施例提供的存储空间是专门分配用于存储特定的数据,所以,不会产生众多文件的访问服务、因为能够提高数据的写入速度,而且,存储空间的大小有限,不会造成过大的内存开销。
在本申请实施例中,所述循环追加写入处理、标记式删除处理、开机检索整理处理和缓冲索引读取处理都是独立的过程,同时也是相辅相成的过程。例如,在每次开机时,均会执行开机检索整理处理过程,开机检索整理处理过程需要根据循环追加写入处理和标记式删除处理过程中写入存储页中的数据记录生成缓存概要表,缓冲索引读取处理过程需要根据缓存概要表中获取待读取的数据的物理地址,然后根据物理地址从存储页中读取数据。上述描述的过程用于举例,在实际应用中,为了保证数据的写入速度、读取速度、存储的数据正确还会存在其它相辅相成的关联信息,例如环形队列描述表、缓存概要表、有效数据、ecc码等。下面通过具体的实施例进行说明,虽然下述实施例按照循环追加写入处理、标记式删除处理、开机检索整理处理、缓冲索引读取处理的顺序进行描述,并不代表在实际应用中也必须按照上述顺序执行操作,实际应用中,每次开机的过程均需要执行开机检索整理处理,从而保证由于设备掉电导致未处理完成的操作不会对存储的数据记录造成破坏。在后续的过程中,可以根据实际需求进行循环追加写入处理、标记式删除处理或缓冲索引读取处理。
图2是本申请实施例提供的一种循环追加写入处理方法的实现流程示意图,该方法是在图1所示实施例的基础上,实施循环追加写入处理的处理过程,如图所示该方法可以包括以下步骤:
步骤s201,在将第n条待存储数据写入所述数据队列的队尾的下一个有效存储页时,将所述第n条待存储数据、第n条待存储数据的标识号和第n条待存储数据的数据长度生成第n条数据记录,并将所述第n条数据记录存储在预设的缓存空间。
在本申请实施例中,虽然数据区用来存储此次存储的数据,然而,在存储时并不仅仅将待存储数据写入数据区,实际上数据区以记录的形式存储了:当前待存储数据的标识号、当前待存储数据的数据长度和当前待存储数据等字段所组成的待存储数据记录,从数据队列的头部回收的有效数据记录和环形队列描述表。并且,排列顺序为:环形队列描述表,当前待存储的数据记录,从数据队列的头部回收的有效数据记录。而冗余区存储了ecc码的三个备份,还有坏块标记等。为待存储数据设置的标识号用于区分不同的数据。
该步骤主要是获取当前待存储数据的数据记录,由于存储页在擦除数据前不能重复写入,所以需要将待存储的所有数据均获取后,才能将所有的数据一次写入下一个有效存储页的数据区和冗余区,可以设置一段缓存空间,在将所有要写入下一个有效存储页的数据全部获取到之前,暂时获取的一部分数据存放在缓存空间中。
步骤s202,从所述数据队列的队头依次回收有效数据记录,并将回收的有效数据记录存储在所述预设的缓存空间。
在本申请实施例中,由于flash存储器的特性,如果一直存储下去,就会将分配的存储空间存满,所以,我们可以设定,在存储新数据的时候,从数据队列的队头(头部)依次回收有效数据记录,如果一个存储页的有效数据记录全部被回收了,则数据队列的队头会变成下一个存储页。
步骤s203,在达到预设的触发机制后,停止回收有效数据记录,生成环形队列描述表,并将所述环形队列描述表存储在所述预设的缓存空间。
在本申请实施例中,有效数据记录不可能一直回收下去,需要设定一定的触发机制,控制回收过程停止,例如,所述预设的触发机制包括:当前回收的有效数据记录的大小导致所述数据队列的队尾的下一个有效存储页无法容纳下一个有效数据记录;或,所述数据队列中的有效数据记录全部被回收。
所述环形队列描述表存储在每一个数据区的起始位置,且所述环形队列描述表包括:写操作序号、当前环形队列的队头的位置和当前环形队列的队尾的位置。写操作序号表示从所对应的软件首次开机运行以来针对存储页的写入次数。
步骤s204,生成ecc码,并根据所述ecc码生成三个备份,将所述ecc码的备份存储在所述预设的缓存空间。
本申请实施例中,还设置了ecc码用于校验数据区数据的正确性,该ecc码可以填写到ecc码的三个备份中,在后续的开机检索整理处理和缓冲索引读取处理中,该ecc码用于验证当前存储页存储的数据的正确性,只有校验通过后,才认为当前存储页存储的数据为正确的,并且,ecc码还具有纠错的功能,关于校验和纠错的处理过程可参见后续的描述。
步骤s205,将所述预设的缓存空间当前存储的所有数据写入所述数据队列的队尾的下一个有效存储页,其中第n条数据记录、回收的有效数据记录、环形队列描述表存储在数据区,且排列顺序为:环形队列描述表、第n条数据记录、回收的有效数据记录,所述ecc码的备份存储在冗余区。
在本申请实施例中,在缓存空间中存储了当前要写入存储页的所有数据后,再将缓存空间中的数据一次写入所述存储页的数据区和冗余区,其中第n条数据记录、回收的有效数据记录、环形队列描述表存储在数据区,所述ecc码的三个备份存储在冗余区,并且,需要说明,所述第n条数据记录、回收的有效数据记录、环形队列描述表在数据区的位置顺序为:环形队列描述表、第n条数据记录、回收的有效数据记录。
步骤s206,在写入完成后,若所述数据队列的队头跨入新的存储块,则将跨过的存储块进行数据擦除处理,并检测擦除处理的存储块是否为坏块。
在本申请实施例中,实际上数据是在进行环形存储,那么刚刚回收的有效数据记录对应的存储页,后续可能还会被写入新数据,为了保证后续写入的正确性,我们可以在写入完成后,将回收的有效数据记录对应的存储页进行擦除操作。然而,基于flash存储器的特性,无法针对每个存储页进行单独的擦除的操作,只能针对每个存储块进行单独的擦除操作,所以,需要查看数据队列的队头是否跨入新的存储块,若所述数据队列的队头跨入新的存储块,则将跨过的存储块进行数据擦除处理,并检测擦除处理的存储块是否为坏块。
步骤s207,若擦除处理的存储块为坏块,则将擦除处理的存储块标记为坏块。
在本申请实施例中,由于数据擦除的过程可能会出现一个或几个位元经擦除后仍为0的情况,这时就表示该存储块为坏块。那么就需要将坏块的存储块标记为坏块,该存储块中的存储页就为无效存储页。这样,在后续的写入操作过程中,就可以直接越过该存储块,向下一个有效存储页进行存储。所述坏块标记可以是坏块标记对应的首字节、尾字节中的任意一者为0x55,如果坏块标记中的字段为0xffff,表示为好块,当然实际应用中,也可以通过其他字符表示坏块,例如0x33等。
在此需要说明,由于存储页在被擦除数据前只能写入一次数据,实际上表示好块的标记0xffff正好为当前存储页的位元擦除后未进行写入的状态,也是擦除后位元未发生错误翻转的状态。表示坏块的标记就指示当前存储块中存在位元发生错误翻转的情况。
为了更清楚的说明本申请实施例中的循环追加写入过程,我们以表1进行说明
表1、循环追加写入处理过程和标记式删除处理过程
作为举例,如表1所示,假设所述存储空间包含了3个存储块:存储块1、存储块2、存储块3,每个存储块包含了4个存储页,且所述存储块均为非坏存储块,即所述存储页均为有效存储页。按照次序存储每一条数据,这里所述数据可以是密钥。为了便于清楚的说明本申请实施例的方案,可以将存储空间的第一个存储页开始,将存储空间中的存储页依次编号为1至12。
假设当前t1时刻存储页5-12中存储的数据形成了数据队列,且存储页5-12中存储的密钥分别为g、h、i、j、k、l、m、n,数据区的密钥记录中除了密钥本身,还存在标识号和密钥长度,当然,每个存储页中的数据区还存储了环形队列描述表、回收的有效数据记录,冗余区存储了坏块标记和ecc码的备份。图示中仅示出了密钥本身和密钥标识号。例如,表中的11表示标识号、对应的g表示密钥本身。那么在将下一条密钥o写入数据队列的队尾的下一个有效存储页时,就需要先根据密钥o、密钥o的标识号99、密钥长度生成密钥记录,并且将密钥记录存储在缓存空间,t2时刻对应的缓存空间中存入了密钥为o的密钥记录。t2时刻对应的存储空间的状态未改变。
继续以表1为例,从数据队列的队头依次回收有效数据记录的过程为:找到所述数据队列的队头(存储页5),从存储页5开始回收有效数据记录,存储页5中的密钥记录g为有效数据记录,需要回收,存储页6中的h为有效数据记录,需要回收,存储页7中的j为有效数据记录,需要回收,存储页8中的j为有效数据记录,需要回收,存储页9中的k有效数据记录,需要回收,……。
在此,我们需要说明有效数据记录的定义,假设一个密钥记录对应的标识号为56,第一次写入的密钥为h、由于用户后续可能会更新所述密钥,所以,第二次写入的(更新的)密钥可能就是k。那么。第一次写入的密钥实际上为56:h,第二次写入的密钥实际上就是56:k,这种情况下,56:h就变成了无效数据记录,56:k就变成了有效数据记录。对于相同的标识号的数据只有最新更新的才认为是有效数据记录,假设存在10个标识号56的数据,则只有最新写入(第10次)的标识号56对应的数据为有效数据记录,之前9次写入的标识号56的数据均变成了无效数据记录。回收的有效数据记录也需要存储在缓存空间。
实际上,在回收有效数据记录的过程中,也是需要进行坏块的检查、以及ecc码的校验和纠错步骤,具体可参照后续的描述。
继续以表1为例,假设回收到存储页9中的有效数据k了,如果继续回收存储页10中的有效数据l,那么就会导致当前回收的所有的有效数据(g、h、i、j、k、l)的大小大于了所述数据队列的队尾的下一个有效存储页(存储页1)的存储容量,及存储页1无法容纳有效数据(g、h、i、j、k、l),只能容纳有效数据(g、h、i、j、k)。这时,就需要停止回收有效数据l。
作为另一种表述,实际上每个存储页的存储空间是有限的,我们需要将回收的有效数据记录也存储在当前存储页1中,所以,我们必须控制回收的有效数据记录的大小,例如,设置一个与存储页的大小相关的第一阈值(第一阈值可以为存储页可容纳的数据量大小),需要控制回收的有效数据记录不能大于第一阈值;回收有效数据记录的过程可以设置为:在需要回收下一条有效数据记录之前,首先计算当前回收的有效数据记录加上下一条有效数据记录后,是否大于第一阈值,若大于了第一阈值,这时就需要停止回收下一条有效数据记录。当然,如果一直将所有的有效数据记录全部回收完毕,所述数据队列的队尾的下一个有效存储页还未存储满,就可以将所述数据队列中的有效数据记录全部回收。
在停止回收有效数据记录后,可以生成环形队列描述表。所述环形队列描述表也需要存储在缓存空间。
后续还需要生成当前存储页的ecc码,并根据所述ecc码生成三个备份,将所述ecc码的备份存储在所述预设的缓存空间;
例如,t3时刻对应的缓存空间中存储了当前待存储数据生成的数据记录、回收的有效数据记录、环形队列描述表、ecc码等。那么t3时刻对应的存储空间中,g、h、i、j、k已经被回收,变成了无效数据。
此时,需要将缓存空间存储的密钥o对应的密钥记录、回收的有效数据记录(g、h、i、j、k)、环形队列描述表存储在数据队列的队尾的下一个有效存储页(存储页1)的数据区,将ecc码的备份存储在冗余区。这是因为数据队列的队尾位于存储页12中,而存储页12是所述存储空间的最后一个有效存储页,那么,所述数据队列的队尾的下一个有效存储页为所述存储空间的第一个有效存储页,即存储页1。对应t4时刻,就是将所述预设的缓存空间当前存储的所有数据写入所述数据队列的队尾的下一个有效存储页,图示中仅示出了密钥o以及密钥o的标识号99。
由于已经回收了有效数据(g、h、i、j、k),在回收有效数据(g、h、i、j、k)之前,数据队列的队头为存储页5,回收有效数据之后,数据队列的队尾变成了存储页9,那么存储页5在存储块2中,存储页9在存储块3中,数据队列的队头从存储块2跨入了存储块3,这时,就表示所述数据队列的队头跨入新的存储块,就可以将跨过的存储块(存储块2)进行数据擦除处理。这时存储块2就可以为后续的写入操作做准备。需要说明,存储块3中的存储页9此时不能进行擦除处理的。表中t5时刻对应的为擦除处理后的存储空间的状态。
还需要说明的是,上述举例的3个存储块以及每个存储块包含4个存储页均用于举例,并不用于限定本申请,实际应用中,所述存储空间可以包含更多的存储块,例如,包含10、50个存储块,每个存储块也可以包含更多的存储页,例如包含32、64或128个存储页,在此不做限制。
图3是本申请实施例提供的一种标记式删除处理方法的实现流程示意图,该方法是在图1所示实施例的基础上,描述标记式删除处理的处理过程,如图所示该方法可以包括以下步骤:
步骤s301,在接收到删除一条数据的指令时,根据待删除数据的标识号生成一条记录长度字段为零的数据记录,并将所述记录长度字段为零的数据记录存储在预设的缓存空间;
步骤s302,从所述数据队列的队头依次回收有效数据记录,并将回收的有效数据记录存储在所述预设的缓存空间;
步骤s303,在达到预设的触发机制后,停止回收有效数据记录,生成环形队列描述表,并将所述环形队列描述表存储在所述预设的缓存空间;
步骤s304,生成ecc码,并根据所述ecc码生成三个备份,将所述ecc码的备份存储在所述预设的缓存空间;
步骤s305,将所述预设的缓存空间当前存储的所有数据写入所述数据队列的队尾的下一个有效存储页,其中记录长度字段为零的数据记录、回收的有效数据记录、环形队列描述表存储在数据区,且排列顺序为:环形队列描述表、记录长度字段为零的数据记录、回收的有效数据记录,所述ecc码的备份存储在冗余区;
步骤s306,在写入完成后,若所述数据队列的队头跨入新的存储块,则将跨过的存储块进行数据擦除处理,并检测擦除处理的存储块是否为坏块;
步骤s307,若擦除处理的存储块为坏块,则将擦除处理的存储块标记为坏块。
在本申请实施例中,图2描述了如何写入一条新的数据,图3所示的实施例描述如何删除一条数据,nandflash的特性不能独立地删除某个存储页中存储的一个数据,只能将某个存储块整体地擦除。所以,为了符合nandflash的特性,本申请实施例制订了特有的删除方式。而删除数据的过程与写入的过程一致,区别在于:在删除操作过程中,生成的数据记录中,所述第n条待存储数据对应为空(即无待存储数据、记录长度字段为零)、第n条待存储数据的标识号为待删除的数据的标识号,第n条待存储数据的数据长度为0,这样,待删除的数据的标识号对应的数据就变成了长度为0的空记录,该标识号之前存储的数据就变成了无效数据,所以相当于将该标识号对应的数据删除了。后续继续按照循环追加写入的方法一样,回收有效数据记录存入缓存空间,生成环形队列描述表存入缓存空间,生成ecc码,并根据所述ecc码生成三个备份存入缓存空间,将所述预设的缓存空间当前存储的所有数据写入所述数据队列的队尾的下一个有效存储页,其中待删除的密钥对应的数据记录(无待存储数据的数据记录、记录长度字段为零)、回收的有效数据、环形队列描述表存储在数据区,所述ecc码的备份存储在冗余区…….
为了清楚地描述删除的过程,我们继续以表1为例,假设t6时刻对应的为删除处理后的存储空间的状态,接收到删除操作的指令后,指令中通常会包括待删除数据的标识号,我们可以将待删除数据的标识号77以及长度为0的空数据生成密钥记录(无当前待存储数据的数据记录或记录长度字段为零的数据记录)后,缓存在缓存空间,前面已经举例说明,当数据队列中存在一个标识号对应了多条数据记录时,最新更新的为有效数据记录,则之前写入的该标识号对应的数据已经变为无效数据记录。即存储页11中对应的数据m已经变成了无效数据,同理,存储页1中回收的有效数据77:m也变成了无效数据记录。
假设存储页2中只能够写入两条有效数据记录,那么在回收有效数据记录时,先从队头(存储页10)回收有效数据记录l,由于存储页11中的数据的标识号77已经更新了新的数据(空),所以存储页11中的m为无效数据,那么继续回收存储页12中的有效数据n,此时回收了有效数据:l、n。将l和n作为回收的有效数据、待删除的标识号77以及密钥长度为0的空密钥生成的密钥记录、环形队列描述表、ecc码备份一起写入存储页2中。同样的,数据队列的队头已经变成了存储页1(从存储块3跨入存储块1),这时就需要对存储块3进行擦除处理。同时检测存储块3是否为坏块,如为坏块,就需要标记为坏块。表1中也仅示出了待删除的密钥对应的长度为0的密钥数据以及标识号,其它数据未示出。
通过对比,也可以发现,实际上删除的操作类似于写入的操作,也可以理解为就是写入新数据的过程,只是写入的新数据为空(长度为0的密钥)。所以,标记式删除的操作和循环追加写入的操作区别在于:删除的数据对应的标识号在新写入的存储页中对应的数据变成了空,由于该标识号更新了新的数据,所以以前的数据就变成了无效数据。由于更新为空,所以表示该标识号对应的数据被删除了,这时如果读取该标识号对应的数据,读取的也应该为空,而不是已经无效的之前的数据。
作为本申请又一实施例,需要说明的是,在将所述预设的缓存空间当前存储的所有数据写入所述数据队列的队尾的下一个有效存储页之前,还包括:
通过存储页的冗余区的坏块标记确定所述数据队列的队尾的下一个有效存储页;
在本申请实施例中,有效存储页为非坏存储块的存储页,所以在确定数据队列的下一个有效存储页时,如果下一个存储页为存储块的第一个存储页,就需要通过坏块标记来确定该存储块是否为坏块,如果为坏块,则跳到下一个存储块,如果不为坏块,则该存储块的第一个存储页就为有效存储页。
所述从所述数据队列的队头依次回收有效数据包括:
在回收每一个有效存储页中的有效数据时,对所述有效存储页中的ecc码进行校验处理获得校验结果;
若所述校验结果为校验成功,则通过缓存概要表确认校验成功的有效存储页内的数据是否为有效数据;
若通过缓存概要表确认校验成功的有效存储页内的数据为有效数据,则将所述有效数据回收。
作为本申请又一实施例,对ecc码进行校验处理获得校验结果包括:
获取当前存储页冗余区的ecc码的所有备份,并将ecc码的所有备份逐位合成为一个ecc码;
将当前存储页数据区获得的ecc码和冗余区合成的ecc码进行对比;
若当前存储页数据区获得的ecc码和冗余区合成的ecc码对比一致,则生成当前存储页的ecc码校验成功的标志;
若当前存储页数据区获得的ecc码和冗余区合成的ecc码对比不一致且指示数据区有一个位元出错,则获取出错位元位置,将出错位元位置对应的数据区的数据取反,并生成当前存储页的ecc码校验成功的标志;
若当前存储页数据区获得的ecc码和冗余区合成的ecc码对比不一致且未指示位元出错信息,则生成当前存储页的ecc码校验失败的标志。
作为本申请又一实施例,所述将ecc码的所有备份逐位合成为一个ecc码包括:
逐位比较所述ecc码的三个备份中同一位置处对应的三个位元;
将三个位元中出现次数最多的位元值作为合成后的ecc码在当前位置处的合成值;
在ecc码的三个备份中所有位置处对应的位元合成后,获得合成后的ecc码。
在本申请实施例中,冗余区的坏块标记用于标记坏块,使得运行中出现的坏块及时被隔离掉;而冗余区存储着ecc码不仅可以用来校验还可以用来纠错。冗余区的ecc码的三个备份,采用少数服从多数的原理、逐位地将这三位合成最终的ecc码,尽可能地避免了冗余区数据自身出错所带来的校验失误问题。例如,假设三个备份中的同一位置上的三个位元分为为001,由于0出现两次,1出现1次,则当前位置的合成值为0,若下一个位置的三个位元分别为101,由于1出现两次,0出现1次,则下一个位置的合成值为1,这样就能得到冗余区三个备份的合成值。
在此,我们需要解释ecc码的生成过程,为保证数据的完整性,用一种指定的算法对原始数据计算出一个校验值(ecc值),并复制成校验值(ecc码)的三个备份。在进行校验时,用同样的算法根据原始数据计算一次校验值(根据当前存储页数据区的数据获得的ecc码),如果再次计算的ecc码和三个ecc码备份合成的ecc码一致,就说明数据区存储的数据是正确、且完整的。
实际应用中,可以将数据区的ecc码和冗余区的ecc合成值进行异或运算,根据ecc的原理和异或运算的结果,得出校验结果;根据校验结果进行如下处理:
若依当前存储页数据区计算出的ecc码和冗余区合成的ecc码对比一致,则生成当前存储页的ecc码校验成功的标志;
若依当前存储页数据区计算出的ecc码和冗余区合成的ecc码对比不一致且指示数据区有一个位元出错,则获取出错位元位置,将出错位元位置对应的数据区的数据取反,并生成当前存储页的ecc码校验成功的标志;该步骤就是纠错的过程。
若依当前存储页数据区计算出的ecc码和冗余区合成的ecc码对比不一致且未指示位元出错信息,则生成当前存储页的ecc码校验失败的标志。
在回收有效数据时,如果为校验成功的标志,则通过缓存概要表继续逐条地确认校验成功的有效存储页内的各条数据记录是否为有效数据记录。这是因为,存储页的ecc码校验成功并不表示该存储页内存储的各数据记录均为有效数据记录,例如,同一密钥标识号对应的密钥有可能会存在更新的过程,假设,存储的标识号77对应的密钥abc存储在存储页23中,但是后续存在更新的过程,将标识号77对应的密钥abc更新为bcd,且存储在存储页29中,此时,在回收有效数据时,回收到存储页23,存储页23中的ecc码是有可能校验成功的,然而,存储页23中存储的密钥abc早已经变成了无效数据,那么如何确定存储页23中存储的abc到底是有效数据还是无效数据,此时可以通过缓存概要表。这是因为,在每次开机时均会根据数据队列生成缓存概要表,且每次循环追加写入处理和标记式删除处理的操作,均会实时更新缓存概要表,因此,可以根据缓存概要表确定校验成功的有效存储页内的数据是否为有效数据。所述缓存概要表的描述以及生成的过程可参见图4所示实施例的描述,在图4所示实施例中描述了缓存概要表的生成过程之后,结合缓存概要表举例说明如何根据缓存概要表确定校验成功的有效存储页内的各条数据记录是否为有效数据记录。
图4是本申请实施例提供的一种开机检索整理处理方法的实现流程示意图,该方法是在图1所示实施例的基础上,描述开机检索整理处理的处理过程,所述开机检索整理处理过程包括:开机检索子流程和开机整理子流程,如图所示,开机检索子流程为步骤s401至步骤s407,该方法可以包括以下步骤:
步骤s401,在所述终端设备开机时,对所述存储空间从头开始逐页地进行检索,获得所述数据队列的队尾所在的存储页,从所述数据队列的队尾所在的存储页数据区的起始位置获取环形队列描述表,并将有效存储块中非空白存储块的脏污信息标志置为第一预设标志。
在本申请实施例中,对数据队列进行检索的过程也需要对每个存储块进行坏块标记检查以及对存储页进行ecc码校验纠错的过程。根据ecc校验纠错的结果将有效存储块(不含坏页的存储页块)中的非空白存储块页的脏污信息标志初始化为第一预设标志。所述第一预设标志用于指示所述存储块内存储的数据为脏污信息。然而,需要说明的一点,在此步骤将所述数据队列中的对应存储块的脏污信息标志置为第一预设标志,并非表示所述数据队列中的存储块中存储的数据记录为脏污信息,而是先将有效存储块中非空白存储块的脏污信息标志初始化为第一预设标志,后续还会根据存储块的实际情况,将部分或者全部存储块的脏污信息标志置为第二预设标志,这里第一预设标志可以是1,第二预设标志可以是0,当然,实际应用中,也可以将第一预设标志设为0,将第二预设标志设为1。同理,还可以将第一预设标志设置为11,将第二预设标志设置为00,在此不做限制。还需要说明的一点为,脏污信息标志是一个数组,数组中的每个变量元素无论是第一预设标志还是第二预设标志均依次对应一个存储块、而不是一个存储页。
在进行检索的过程中,若检查到空白页,则表明上一个有效存储页为所述数据队列的队尾所在的存储页,那么环形队列描述表就是从所述数据队列的队尾所在的存储页中数据区的起始位置获得的。
步骤s402,从所述环形队列描述表中获得所述数据队列的队头,并将所述数据队列的队头的存储位置、所述数据队列的队尾的存储位置写入缓存概要表。
在本申请实施例中,如前所述,环形队列描述表中存储当前数据队列的队头的存储位置,此时,可以将当前数据队列的队头和队尾的存储位置写入缓存概要表。
步骤s403,从所述数据队列的队头开始,依次检索和校验所述数据队列的每个存储页中的数据,并将所述数据队列中的对应存储块的脏污信息标志置为第二预设标志。
在本申请实施例中,需要将数据队列从队头到队尾之间的所有存储块的脏污信息标志置为第二预设标志,所述第二预设标志用于表示存储块中存储的数据记录为非脏污信息,需要说明的是,这里也并非就表示数据队列的队头和队尾之间不存在脏污信息,而是因为,该步骤中置为第二预设标志的目的是将数据队列的队头和队尾以外的脏污块进行擦除处理。所以,在此设计为将所述数据队列中的对应存储块的脏污信息标志置为第二预设标志。这里需要说明,脏污块表示的为数据队列的队头至队尾以外的区域中包含了脏污数据的存储块,即数据队列的队头至队尾以外的区域中的非空白存储页。
获取了数据队列的队头之后,就需要依次执行存储块的坏块标记检查和ecc码校验纠错过程。例如步骤s404至步骤s407。
步骤s404,若当前存储页为存储块的首页,则根据当前存储页冗余区的坏块标记判断当前存储页对应的存储块是否为坏块。
步骤s405,若为坏块,则跳到下一个存储块,并将下一个存储块的第一个存储页作为当前存储页。
步骤s406,若不为坏块,则对所述当前存储页中的ecc码进行校验处理获得校验结果。
步骤s407,若所述校验结果为校验成功,则将当前存储页内存储的数据的标识号和存储位置写入缓存概要表。
在本申请实施例中,如果当前存储页检验结果为校验成功(即进行过校验和纠错的过程),此时,还需要将当前存储页存储的密钥标识号和对应的存储位置写入缓存概要表,以便于后续的回收操作。
所述开机整理子流程包括:
步骤s408,根据存储块的脏污信息标志确定当前存储块是否为脏污块。
在本申请实施例中,如前所述,所述脏污信息标志为数组变量的形式。
步骤s409,若当前存储块为脏污块,则对当前存储块进行数据擦除处理,并检测擦除处理的存储块是否为坏块。
步骤s410,若擦除处理的存储块为坏块,则将擦除处理的存储块标记为坏块。
在本申请实施例中,由于最初将各非空白存储页所在存储块的脏污标志全部初始化为“脏污”,然后在确定存储页中的数据不为脏污信息后,将对应块的脏污信息标志清除了,所以,可以认定脏污信息标识为“脏污”的存储块中的数据为脏污信息,脏污信息标志被清除了或者变成了非脏污信息的存储块中的数据为非脏污信息。只需要根据存储块对应的脏污信息标志确定每个存储块中的存储页是否全部为脏污信息,如果是,则当前存储块为脏污块,就需要对当前存储块进行数据擦除处理。并进行后续的坏块检查标记的操作。
在本申请实施例中,所述缓存概要表缓存在随机存储内存(ram)中,生成的缓存概要表也包括:所述数据队列的队头的存储位置、所述数据队列的队尾的存储位置、每条数据记录的标识号、每条数据记录当前的存储位置。另外,需要说明的是,所述缓存概要表存储在ram中,所以,缓存概要表中的数据是允许被更新的,例如,从所述数据队列的队头开始,依次检索和校验所述数据队列的每个存储页中的数据,在当前存储页校验成功,则将当前存储页内存储的数据的标识号和存储位置写入缓存概要表,那么此时是无法区分当前存储的标识号对应的存储位置中存储的数据记录是不是有效数据,但是,本申请实施例中需要从数据队列的队头开始一直到队尾,均会进行上述检索检验的过程,因此,即使在某一次写入缓存概要表中的存储位置对应的数据记录不是有效数据时,也会被后续的有效数据更新掉。即当检索和校验到队尾时,缓存概要表中存储的每条数据记录的存储位置最终均对应地为有效的数据记录的位置。
上述描述的过程均以概括性的语言描述开机检索整理处理的过程,省略了一些具体的处理过程,为了进一步说明开机检索整理处理的过程,以密钥存储为例进行描述,其中以下描述中的页指的是存储页。
首先,设分配存储空间的总存储块数为bs,每存储块的页数为ps,每存储页的数据字节数为ds;设所分配的存储块的总页数为tps,显然,tps=bs×ps。所分配的存储块数bs至少应大于1,典型取值为10;每存储块的页数ps和每存储页的数据字节数ds由所采用nandflash芯片的规格所决定,ps典型规格为64页、ds典型规格为2048数据字节。
一个存储页是每次写入的最小单位,每个存储页由数据区和冗余区组成。数据区包括环形队列描述表和若干数据记录,环形队列描述表长度固定、位于数据区头部,数据记录长度不固定、紧接着存放在环形队列描述表的后面、不跨页存放;冗余区存放着校验记录,它包括坏块标记、ecc值的三个备份等。
环形队列描述表存放在每个存储页数据区的开始处,由标签、写操作序号、起始偏移页号等字段组成,共8字节,其结构采用c语言描述如下:
structring_queue_descriptor
{
chartag[2];//标签字段:固定为“kh”,表示一个合法的环形队列描述表
unsignedlongwrite_seqno;//写操作序号字段:表示对数据存储页的写操作顺序号,最大的就是尾巴,最小的就是头。
unsignedshortstart_page;//起始偏移页号字段:起始记录在整个数据存储区内的偏移页号
}
冗余区的校验记录存放在每个存储页冗余区的开始处,其结构采用c语言描述如下:
structverify_record
{
charbad_id[2];//坏块标记,任一字节为0x55表示为坏块
longecc_code1;//错误验证与纠错码备份1
longecc_code2;//错误验证与纠错码备份2
longecc_code3;//错误验证与纠错码备份3
}
缓存概要表由最新写操作序号、起始偏移页号、终止偏移页号、密钥位映像、密钥记录偏移等字段组成,反映了数据存储区中密钥连续存放的起止位置、最新写操作序号、各密钥的有效性等信息,其结构采用c语言描述如下:
#definen64//系统所支持的密钥总个数,可根据实际需要调整,需为8的整数倍
structkeys_info
{
unsignedlongwrite_seqno;//最新写操作序号字段:表示对密钥存储页的最新写操作顺序号
unsignedushortstart_page;//起始偏移页号字段:起始记录在整个密钥存储区内的偏移页号
unsignedushortend_page;//终止偏移页号字段:终止记录在整个密钥存储区内的偏移页号
boolbitmap[n]:1;//位映像字段:为1表示对应密钥有效、为0表示对应密钥无效
longkey_offset[n];//密钥记录偏移字段:各密钥在密钥存储区中以字节为单位的偏移
}
坏块标记数组变量中任一字节为0x55表示为坏块,在位映像字段中,各密钥的有效性依次存放,bitmap[j]记录密钥j的有效性,其中,j是[0,n-1]范围内的整数,即密钥的标识号;同样地,在密钥偏移字段中,key_offset[j]记录密钥j在密钥存储区中的字节偏移量。具体的步骤如下:
步骤a、定义缓存概要表全局变量t,用于整个密钥的管理。将终止偏移页号字段初始化为-1,将密钥记录偏移字段的各元素均初始化为-1,将其它字段均清零。
定义如下局部变量,用于检索页数据:
当前页的页号:cpn;当前页的写操作序号:csn;
上一页的页号:ppn;上一页的写操作序号:psn。
最近写入的页号:lpn,用于指示最近一次写入操作对应的页号。
将变量cpn、csn清零,将变量ppn、psn、lpn初始化为-1。
注:所分配存储空间起始页的页号为0,后续每一页的页号依次增1。
定义块脏污标志数组变量:boolblock_dirty[bs],用于开机整理子流程,将此数组清零。
步骤b、读取cpn对应页的整页包括数据区和冗余区的所有数据。
步骤c、如果cpn对应页是块首页(即cpn%ps等于0),则检查冗余区的坏块标记:
若坏块标记的首字节、尾字节中的任意一者为0x55,则判断cpn对应数据块为坏块,忽略该块、并将cpn增大ps后跳转步骤b。
否则,继续下一步。
步骤d、执行ecc校验与纠错步骤:
d1、计算数据区所有数据的ecc值用于校验数据的准确性。
d2、将冗余区ecc码的三个备份如下逐位合成为一个ecc值(称为ecc合成值):
逐位比较三个备份中的同一位置处的三个位元,取三者中出现两次或三次的位元值为该位元的合成值。
例如:若第m位上的三个位元值分别为0、0、1,由于0出现两次,则第m位的合成值为0;若第m+1位上三个位元值分别为1、0、1,由于1出现两次则第m+1位的合成值为1。
d3、将计算的数据区的ecc值与ecc合成值进行异或运算。
d4、根据ecc的原理和异或运算的结果,得出校验结果;根据校验结果进行如下处理:
若校验通过,则置ecc校验成功标志;
若校验不通过且指示数据区位元有一位出错,则按ecc纠错方法从异或运算结果中得到出错位元的位置,再将读出的数据区数据中的该位出错位元取反,并置ecc校验成功标志;
若校验不通过且指示其它任何出错情况,则置ecc校验失败标志。
步骤e、根据上述ecc校验标志进行如下处理:
若校验失败且csn非零(表明已搜索到有效页),则检查该页是否空白页(即:所有数据字节均为0xff):
若不为空白页,则将对应块脏污标志位元置1(即:block_dirty[cpn/ps]=1,下同)。
若为空白页,表明上一页是存储区中的最近一次写入页,则跳转步骤g。
若校验失败且csn为零(表明尚未搜索到有效页),则将对应块脏污标志位元置1。
若校验成功,则将对应块脏污标志位元置1,并更新当前页的写操作序号csn:从读取到的数据区数据中取出环形队列描述表的写操作序号字段值,将该值赋给csn。接着,更新上一页变量ppn和psn:使ppn等于cpn,使psn等于csn。
步骤f、将cpn赋值给记录最近写入页号的变量lpn,再将cpn增1,接着检查是否已超过存储区尾部,即:cpn>tps是否成立。
若未超过,则跳转步骤b。
若已超过,则转下一步。
步骤g、检查csn的值,并进行如下跳转或赋值处理:
若csn为零,表明未搜索到任何有效页,则终止检索、并转步骤o执行整理子过程。
若csn非零,表明已搜索到有效页,则读取ppn对应页的数据区数据(ppn是存储区最近一次有效写入页的页号),从该数据的头部取得对应的环形队列描述表结构数据r。
按如下方式填写缓存概要表t中的下列字段:
将r的写操作序号加一后,赋给t的最新写操作序号字段。
将r的起始偏移页号字段值复制到t的起始偏移页号字段。
将最近写入页号lpn的值赋给t的终止偏移页号字段。
步骤h、令cpn等于t的起始偏移页号。
步骤i、读取cpn对应页的整页包括数据区和冗余区的所有数据,并将对应块脏污标志位元清零,即:block_dirty[cpn/ps]=0。
步骤j、如果cpn对应页是块首页(即cpn%ps等于0),则判断冗余区的坏块标志:
若坏块标记的首字节、尾字节中的任意一者为0x55,则判断cpn对应数据块为坏块,忽略该块、将cpn增大ps并抹除tps后跳转步骤i。
否则,继续下一步。
步骤k、执行与步骤d中相同的ecc校验与纠错步骤,得到ecc校验成功或失败标志。
并根据ecc校验标志进行如下处理:
若校验失败,则丢弃该页,将cpn增一再模除存储区总页数tps(使页号自动回绕,下同)、再跳转步骤i。
若校验成功,则更新当前页的写操作序号csn,即:将r的写操作序号值赋值给csn。
步骤l、检索cpn对应页数据中的各密钥记录,将检索出的密钥记录的位置信息填入t的密钥记录偏移字段,并更新t的位映像字段。
在cpn对应页数据中检索密钥记录的具体步骤如下:
l1、定义一个局部变量page_offset,表示从本数据页起始处开始的偏移字节数。
将page_offset初始化为环形队列描述表r的长度。
l2、对读出的页数据,从page_offset指示的位置,读出一条密钥记录的前4字节。
注:本方案将一条密钥记录分成密钥标识号、本记录长、密钥信息串等三个字段,其格式采用c语言的结构类型示意如下:
structkey_record
{
unsignedshortkey_id;//密钥标识号,有效范围:1-n
unsignedshortrec_len;//本记录长:本记录的总字节数
unsignedcharkey_block[v];//密文形式的、长度为v的密钥信息串
}
注:key_block字段是一个可变长的数组,即:不同记录中的key_block字段长度v可能相同、也可能不尽相同。它用于存放密钥的长度、用途、版本号、有效期、密钥数据等信息,该信息以密文形式存放,即:将其明文信息采用一个存放在sram中的系统密钥加密后存放进来。如果是对称密钥,其长度一般是二、三十字节;如果是非对称密钥,其长度一般是一、两百字节。
这样,就依次得到密钥标识号i和本记录长l。
若两者均等于0xffff,这说明页数据已检索完毕,则终止该页的检索过程。
l3、根据本记录长l的值进行相应处理:
若l等于0,表示该密钥从此被删除,则将t的密钥偏移相应位清零、并将密钥记录偏移字段相应元素写为-1,即:t.bitmap[i]=0,t.key_offset[i]=-1。
若l非0,表示该密钥有效,则将t的密钥偏移相应位写入1、并将该密钥的位置信息写入密钥记录偏移字段的相应元素,即:t.bitmap[i]=1,t.key_offset[i]=cpn*ds+page_offset。
l4、将page_offset的值增大l,即:page_offset=page_offset+l。
l5、检查是否已到页尾,即:ds-page_offset≤4是否成立。
若不成立,则转l2,继续检索过程。
若成立,表明检索位置已到页尾,则终止该页的检索过程。
步骤m、将cpn增1,再抹除存储区总页数tps。
步骤n、检查是否已到达环形队列尾部,即cpn是否大于t的终止偏移页号字段的值。
若否,则跳转步骤i、继续下一页的检索过程。
若是,就表明所有相关页已全部检索完毕,则终止检索、继续下一步的整理子过程。
步骤o、执行开机整理子流程,具体步骤如下:
o1、定义临时变量k,将k清零。
o2、检查块号k是否为脏块,即:block_dirty[k]是否为1。
若否,则转o4;
若是,则继续下一步。
o3、将数据块k执行块擦除操作,并检查块擦除操作的执行结果。
若擦除失败,则在块k的首页写入坏块标记,即:将校验记录的坏块标记字段设置为0x5555,并将该两字节数据写入首页冗余区的起始处,页内其它位置均不作写入。
若擦除成功,则继续下一步。
o4、将k增1。
o5、检查是否已遍历所有存储块,即:k是否等于bs。
若否,则转o2。
若是,则结束开机整理子过程。
结合上述实施例,继续以密钥存储为例,说明如何实施循环追加写入处理的过程。
步骤x1、定义如下局部变量,用于从循环队列起始页回收密钥记录:
起始页的页号spn;
起始页页号备份spn’,用于数据块擦除操作;
起始页内的偏移soffset,表示从起始页起始处开始的偏移字节数;
终止页内的偏移eoffset,表示从终止页起始处开始的偏移字节数;
页数据缓存spage[ds+14],这里,ds是存储页数据区的大小,14是冗余区校验记录的大小,用于存放从起始页中读取的暂存数据;
页数据缓存epage[ds+14],用于存放将写入终止页的暂存数据。
进行变量初始化:令spn等于缓存概要表t的起始偏移页号字段值;令soffset和eoffset均等于环形队列描述表的长度;令spn’等于spn。
步骤x2、根据密钥写入请求、按步骤l所规定的密钥记录格式生成一条密钥记录,即:填写好密钥标识号、本记录长和密钥信息串等字段。
密钥标识号i、密钥信息串及其长度可从应用层软件的密钥写入请求中获取;本记录长l1通过将该三部分的总长度相加后得到。
将该记录写入epage的eoffset偏移处;接着更新偏移值,即:eoffset=eoffset+l1。
步骤x3、更新t的终止偏移页号字段:
将终止偏移页号字段的值增1、并抹除存储区总页数tps(被请求写入的密钥以及回收的若干密钥记录将写入该页号对应的存储页中);
步骤x4、检查是否已抵达环形队列尾部,即:spn==t.end_page是否成立。
若是,则终止本复制过程、转步骤x8。
若否,则读取spn对应页的整页包括数据区和冗余区的所有数据,暂存到spage。
步骤x5、如果spn对应页是块首页(即spn%ps等于0),则检查冗余区的坏块标志:
若坏块标记的首字节、尾字节中的任意一者为0x55,则判断spn对应数据块为坏块,接着,忽略该块、将spn增大ps并抹除tps后跳转步骤x4。
否则,继续下一步。
步骤x6、执行与步骤d中相同的ecc校验与纠错步骤,得到ecc校验成功或失败标志。
根据ecc校验标志进行如下处理:
若校验失败,则丢弃该页,将spn增1再抹除存储区总页数tps、再跳转步骤x4。
若校验成功,则继续下一步。
步骤x7、检索spage中的各密钥记录,将其中的若干有效密钥记录复制到页数据缓存epage中。
spage中的具体复制过程如下:
步骤x7.1、从soffset偏移处开始,读取4字节,依次得到密钥标识号i和本记录长l。
若两者均等于0xffff,说明本页已再无密钥记录,则结束本过程。
步骤x7.2、计算该密钥对应的偏移量p,即:p=spn*ds+soffset。
步骤x7.3、检查偏移量p与缓存概要表中该密钥对应的密钥记录偏移值key_offset[i]是否相等。
若不相等,表明该密钥记录已失效,则忽略该记录、转步骤x7.6;
若相等,表明该密钥记录有效,则继续下一步操作。
步骤x7.4、检查epage是否还能容纳密钥记录i,即:eoffset+l≤ds是否成立。
若不成立,则终止本复制过程、转步骤x8。
若成立,则继续下一步操作。
步骤x7.5、将本记录复制到epage中,并更新终止页偏移eoffset,即:eoffset=eoffset+l。
步骤x7.6、更新起始页偏移soffset,即:soffset=soffset+l。
步骤x7.7、检查是否已抵达起始页尾,即:ds-soffset≤4是否成立。
若不成立,则转步骤x7.1,继续本页内的复制过程。
若成立,表明检索位置已到页尾,则继续下一步操作。
步骤x7.8、将起始页号spn增1并抹除存储区总页数tps,即:spn=(spn+1)%tps。
步骤x7.9、转步骤x4,继续下一页的检索与复制过程。
步骤x8、填写终止页环形队列描述表er的各字段,按如下操作:
将标签字段设置为“kh”;
将缓存概要表的最新写操作序号字段值赋给er的写操作序号字段;
将spn的值赋给er的起始偏移页号字段;
并将填写好的er数据复制到epage的起始处。
步骤x9、生成页数据缓存的ecc码,并将ecc码同时填写到校验记录中ecc值的三个备份中;将坏块标记字段设置为0xffff,示意为好块。
将填写好的校验记录复制到epage的ds偏移处。
步骤x10、检查待写入页是否是坏块首页。
如果终止偏移页(页号从t的终止偏移页号字段获取,下同)是块首页(即spn%ps等于0),则读取该页冗余区的坏块标志,并检查该坏块标志:
若坏块标记的首字节、尾字节中的任意一者为0x55,则判断当前终止页对应数据块为坏块,接着,忽略该块、将t的终止偏移页号字段增大ps并抹除tps后跳转步骤10。
否则,继续下一步。
步骤x11、将epage的所有数据写入密钥存储块的终止页。
步骤x12、根据起始页页号spn、起始页页号备份spn’的值,计算出是否出现废弃脏页,并对脏页进行擦除处理。
具体擦除处理过程如下:
步骤x12.1、计算起始页页号备份spn’对应的块号b1,即:b1=spn’/ps;
计算起始页页号spn对应的块号b2,即:b2=spn/ps;
计算待擦除的块数ebs,即:ebs=(b2+bs-b1)%bs。
定义变量abs,表示已擦除的块数,使之初始化为0。
步骤x12.2、检查abs与ebs是否相等。
若成立,表明已无需擦除处理,则终止擦除处理过程。
若不成立,则继续下一步。
步骤x12.3、从数据块b1首页的冗余区起始处读取两字节,即坏块标记字段。
若坏块标记的首字节、尾字节中的任意一者为0x55,则判断数据块b1为坏块,忽略该块、并跳转步骤x12.5。
步骤x12.4、将数据块b1执行块擦除操作,并检查块擦除操作的执行结果。
若擦除失败,则在块b1的首页写入坏块标记,即:将校验记录的坏块标记字段设置为0x5555,并将该两字节数据写入首页冗余区的起始处,页内其它位置均不作写入。
若擦除成功,则继续下一步。
步骤x12.5、将b1的值增1,并抹除bs,即:b1=(b1+1)%bs。
步骤x12.6、将abs的值增1后,转步骤x12.2。
步骤x13、更新t的剩余字段:
将最新写操作序号字段值增1;
将spn的值赋给起始偏移页号字段。
将位映像字段中待写入密钥的对应元素置1;
更新待写入密钥对应的密钥记录偏移字段元素,即:t.key_offset[i]=终止偏移页号*ds+环形队列描述表的长度。
由于标识式删除处理和循环追加写入处理的过程大致相同,所以,以下简要叙述标识式删除的过程。
终端设备中的密钥管理模块接收应用层软件发起的一条密钥删除请求后,检查t的位映像字段中与被请求删除密钥的标识号对应的元素:若该元素为0,则中止删除过程,并向应用层报告“请求删除的密钥不存在”;若该元素为1,则开始执行标记式删除子流程。
标记式删除子流程的具体步骤如下:
步骤b1、定义如下局部变量,用于从循环队列起始页回收密钥记录:
起始页的页号spn;
起始页页号备份spn’,用于数据块擦除操作;
起始页内的偏移soffset,表示从起始页起始处开始的偏移字节数;
终止页内的偏移eoffset,表示从终止页起始处开始的偏移字节数;
页数据缓存spage[ds+14],这里,ds是存储页数据区的大小,14是冗余区校验记录的大小,用于存放从起始页中读取的暂存数据;
页数据缓存epage[ds+14],用于存放将写入终止页的暂存数据。
进行变量初始化:令spn等于t的起始偏移页号字段值;令soffset和eoffset均等于环形队列描述表的长度;令spn’等于spn。
步骤b2、根据密钥删除请求、按步骤l所规定的密钥记录格式生成一条无密钥信息串的密钥记录,即:只填写密钥标识号、本记录长等字段。
其中:密钥标识号i可从应用层软件的密钥删除请求中获取;记录总长l1等于4。
将该记录写入epage的eoffset偏移处;接着更新偏移值,即:eoffset=eoffset+l1。
步骤b3、更新t的终止偏移页号字段:
将终止偏移页号字段的值增一,并模除存储区总页数tps(被请求删除的密钥以及回收的若干密钥记录将写入该页号对应的存储页中);
步骤b4~步骤b12:与前述密钥写入流程中的步骤x4至步骤x12的所有步骤相同,为了叙述简洁性,在此略去、不再赘述。
4.13更新t的剩余字段:
将最新写操作序号字段值增1;
将spn的值赋给起始偏移页号字段。
将位映像字段中待删除密钥的对应元素清零,标记该密钥已失效和不存在;
更新待删除密钥对应的密钥记录偏移字段元素,即:t.key_offset[i]=-1。
作为本申请又一实施例,还提供一种缓冲索引读取处理方法,该方法是在图4所示实施例的基础上,实施缓冲索引读取处理的处理过程,该方法可以包括以下步骤:
在接收到读取数据的指令时,根据所述指令中的标识号,从所述缓存概要表中获取所述指令中的标识号对应数据的存储位置;
对所述存储位置对应的存储页中的ecc码进行校验处理获得校验结果;
若所述校验结果为校验成功,则基于所述存储地址读取所述指令中的标识号对应的数据。
在本申请实施例中,由于每次开机操作均会生成缓存概要表,所以,读取数据记录时,通过读取数据的指令中给定的标识号,可以在缓存概要表获取到该标识号对应的数据在flash中的物理存储地址,从而可快速读取到该标识号对应的数据。这种读取方式,不需要在flash中重新逐条检索和搜寻数据,是借助ram中的缓存概要表来快速进行的。因此,能够具有较快的读取速度。需要说明一点,若校验未通过,表示要读取的数据损坏。ecc码校验的过程不再赘述,参照前述的实施例的相关描述。
通过对开机检索整理处理的过程描述,可以看出,缓存概要表在每次开机的时候均会生成,可以通过缓存概要表实现缓冲索引读取处理,然后,在开机之后写入或删除的数据记录时,在每次将所述预设的缓存空间当前存储的所有数据写入所述数据队列的队尾的下一个有效存储页之后,会根据当前写入的数据记录,更新所述缓存概要表,这样,所述缓存概要表就能实时、准确地反映flash中各记录的存续状态与最新位置信息。
图5是本申请一实施例提供的终端设备的示意框图,为了便于说明,仅示出与本申请实施例相关的部分。
该终端设备5可以是内置于手机、平板电脑、笔记本、计算机等终端设备内的软件单元、硬件单元或者软硬结合的单元,也可以作为独立的挂件集成到所述手机、平板电脑、笔记本、计算机等终端设备中。
所述终端设备5包括:
获取模块51,用于获取分配的存储空间,所述存储空间包括至少两个存储块,每个存储块包括至少两个存储页,每个存储页的大小相等;
存储模块52,用于将获取的每条待存储数据依次写入所述存储空间的存储页中,所述存储空间中写入的数据形成数据队列;
处理模块53,用于基于所述存储空间中写入的数据队列进行数据处理,所述数据处理包括:循环追加写入处理、标记式删除处理、开机检索整理处理、缓冲索引读取处理。
可选的,每条数据不跨页存储,所述存储页在被擦除数据前允许写入一次数据;
所述存储页包括数据区和冗余区,所述数据区用于存储当前写入的数据;所述冗余区包括用于标记坏块的坏块标记和用于校验数据区的数据正确性的ecc码。
可选的,所述存储模块52包括:
第一存储单元,用于在接收到存储第一条待存储数据的指令后,将第一条待存储数据写入所述存储空间的有效存储页中,所述有效存储页为非坏存储块中的存储页;
第二存储单元,用于在接收到存储第n条待存储数据的指令后,将第n条待存储数据写入所述数据队列的队尾的下一个有效存储页,其中,n为大于1的自然数,当所述数据队列的队尾在所述存储空间的最后一个有效存储页时,所述数据队列的队尾的下一个有效存储页为所述存储空间的第一个有效存储页。
可选的,所述处理模块53包括:循环追加写入单元531,
所述循环追加写入单元531包括:
第一数据记录生成子单元,用于在将第n条待存储数据写入所述数据队列的队尾的下一个有效存储页时,将所述第n条待存储数据、第n条待存储数据的标识号和第n条待存储数据的数据长度生成第n条数据记录,并将所述第n条数据记录存储在预设的缓存空间;
第一有效数据回收子单元,用于从所述数据队列的队头依次回收有效数据记录,并将回收的有效数据记录存储在所述预设的缓存空间;
第一描述表生成子单元,用于在达到预设的触发机制后,停止回收有效数据记录,生成环形队列描述表,并将所述环形队列描述表存储在所述预设的缓存空间;
第一ecc码生成子单元,用于生成ecc码,并根据所述ecc码生成三个备份,将所述ecc码的备份存储在所述预设的缓存空间;
第一写入子单元,用于将所述预设的缓存空间当前存储的所有数据写入所述数据队列的队尾的下一个有效存储页,其中第n条数据记录、回收的有效数据记录、环形队列描述表存储在数据区,且排列顺序为:环形队列描述表、第n条数据记录、回收的有效数据记录,所述ecc码的备份存储在冗余区;
第一擦除子单元,用于在写入完成后,若所述数据队列的队头跨入新的存储块,则将跨过的存储块进行数据擦除处理,并检测擦除处理的存储块是否为坏块;
第一坏块标记子单元,用于若擦除处理的存储块为坏块,则将擦除处理的存储块标记为坏块。
可选的,所述处理模块53包括:标记式删除单元532,
所述标记式删除单元532包括:
第二数据记录生成子单元,用于在接收到删除一条数据的指令时,根据待删除数据的标识号生成一条记录长度字段为零的数据记录,并将所述记录长度字段为零的数据记录存储在预设的缓存空间;
第二有效数据回收子单元,用于从所述数据队列的队头依次回收有效数据记录,并将回收的有效数据记录存储在所述预设的缓存空间;
第二描述表生成子单元,用于在达到预设的触发机制后,停止回收有效数据记录,生成环形队列描述表,并将所述环形队列描述表存储在所述预设的缓存空间;
第二ecc码生成子单元,用于生成ecc码,并根据所述ecc码生成三个备份,将所述ecc码的备份存储在所述预设的缓存空间;
第二写入子单元,用于将所述预设的缓存空间当前存储的所有数据写入所述数据队列的队尾的下一个有效存储页,其中记录长度字段为零的数据记录、回收的有效数据记录、环形队列描述表存储在数据区,且排列顺序为:环形队列描述表、记录长度字段为零的数据记录、回收的有效数据记录,所述ecc码的备份存储在冗余区;
第二擦除子单元,用于在写入完成后,若所述数据队列的队头跨入新的存储块,则将跨过的存储块进行数据擦除处理,并检测擦除处理的存储块是否为坏块;
第二坏块标记子单元,用于若擦除处理的存储块为坏块,则将擦除处理的存储块标记为坏块。
可选的,所述预设的触发机制包括:
当前回收的有效数据记录的大小导致所述数据队列的队尾的下一个有效存储页无法容纳下一个有效数据记录;
或,所述数据队列中的有效数据记录全部被回收。
可选的,所述环形队列描述表存储在数据区的起始位置,且所述环形队列描述表包括:写操作序号、当前环形队列的队头的位置和当前环形队列的队尾的位置。
可选的,所述循环追加写入单元531和所述标记式删除单元532均包括:下一个有效存储也确定子单元;
所述下一个有效存储也确定子单元用于:
通过存储页的冗余区的坏块标记确定所述数据队列的队尾的下一个有效存储页;
所述第一有效数据回收子单元和第二有效数据回收子单元均用于:
在回收每一个有效存储页中的有效数据记录时,对所述有效存储页中的ecc码进行校验处理获得校验结果;
若所述校验结果为校验成功,则通过缓存概要表确认校验成功的有效存储页内的数据是否为有效数据记录;若通过缓存概要表确认校验成功的有效存储页内的数据为有效数据记录,则将所述有效数据记录回收。
可选的,所述处理模块53包括:开机检索整理单元533,
所述开机检索整理单元533包括:开机检索子流程单元和开机整理子流程单元;
所述开机检索子流程单元用于:
在所述终端设备开机时,对所述存储空间从头开始逐页地进行检索,获得所述数据队列的队尾所在的存储页,从所述数据队列的队尾所在的存储页数据区的起始位置获取环形队列描述表,并将有效存储块中非空白存储块的脏污信息标志置为第一预设标志,所述有效存储块为非坏存储块;
从所述环形队列描述表中获得所述数据队列的队头,并将所述数据队列的队头的存储位置、所述数据队列的队尾的存储位置写入缓存概要表;
从所述数据队列的队头开始,依次检索和校验所述数据队列的每个存储页中的数据,并将所述数据队列中对应存储块的脏污信息标志置为第二预设标志;
若当前存储页为存储块的首页,则根据当前存储页冗余区的坏块标记判断当前存储页对应的存储块是否为坏块;
若为坏块,则跳到下一个存储块,并将下一个存储块的第一个存储页作为当前存储页;
若不为坏块,则对所述当前存储页中的ecc码进行校验处理获得校验结果;
若所述校验结果为校验成功,则将当前存储页内存储的数据标识号和对应存储位置写入缓存概要表;
所述开机整理子流程单元用于:
根据存储块脏污信息标志数组变量确定当前存储块是否为脏污块;
若当前存储块为脏污块,则对当前存储块进行数据擦除处理,并检测擦除处理的存储块是否为坏块;
若擦除处理的存储块为坏块,则将擦除处理的存储块标记为坏块。
可选的,所述处理模块53还包括:缓冲索引读取单元534;
所述缓冲索引读取单元534包括:
存储位置获取子单元,用于在接收到读取数据的指令时,根据所述指令中的标识号,从所述缓存概要表中获取所述指令中的标识号对应数据的存储位置;
ecc码校验子单元,用于对所述存储位置对应的存储页中的ecc码进行校验处理获得校验结果;
数据读取子单元,用于若所述校验结果为校验成功,则基于所述存储地址读取所述指令中的标识号对应的数据。
可选的,所述ecc码校验子单元还用于:
获取当前存储页冗余区的ecc码的所有备份,并将ecc码的所有备份逐位合成为一个ecc码;
将依当前存储页数据区计算出的ecc码和冗余区合成的ecc码进行对比;
若依当前存储页数据区计算出的ecc码和冗余区合成的ecc码对比一致,则生成当前存储页的ecc码校验成功的标志;
若依当前存储页数据区计算出的ecc码和冗余区合成的ecc码对比不一致且指示数据区有一个位元出错,则获取出错位元位置,将出错位元位置对应的数据区的数据取反,并生成当前存储页的ecc码校验成功的标志;
若依当前存储页数据区计算出的ecc码和冗余区合成的ecc码对比不一致且未指示位元出错信息,则生成当前存储页的ecc码校验失败的标志。
可选的,所述ecc码校验子单元还用于:
逐位比较所述ecc码的三个备份中同一位置处对应的三个位元;
将三个位元中出现次数最多的位元值作为合成后的ecc码在当前位置处的合成值;
在ecc码的三个备份中所有位置处对应的位元合成后,获得合成后的ecc码。
可选的,所述循环追加写入单元531还包括:
更新子单元,用于根据当前写入的数据记录,更新所述缓存概要表。
所述标记式删除单元532还包括:
更新子单元,用于根据当前写入的数据记录,更新所述缓存概要表。
所属领域的技术人员可以清楚地了解到,为了描述的方便和简洁,仅以上述各功能单元、模块的划分进行举例说明,实际应用中,可以根据需要而将上述功能分配由不同的功能单元、模块完成,即将所述终端设备的内部结构划分成不同的功能单元或模块,以完成以上描述的全部或者部分功能。实施例中的各功能单元、模块可以集成在一个处理单元中,也可以是各个单元单独物理存在,也可以两个或两个以上单元集成在一个单元中,上述集成的单元既可以采用硬件的形式实现,也可以采用软件功能单元的形式实现。另外,各功能单元、模块的具体名称也只是为了便于相互区分,并不用于限制本申请的保护范围。上述终端设备中单元、模块的具体工作过程,可以参考前述方法实施例中的对应过程,在此不再赘述。
图6是本申请又一实施例提供的终端设备的示意框图。如图6所示,该实施例的终端设备6包括:一个或多个处理器60、存储器61以及存储在所述存储器61中并可在所述处理器60上运行的计算机程序62。所述处理器60执行所述计算机程序62时实现上述各个数据存储方法实施例中的步骤,例如图1所示的步骤s101至s103。或者,所述处理器60执行所述计算机程序62时实现上述终端设备实施例中各模块/单元的功能,例如图5所示模块51至53的功能。
示例性的,所述计算机程序62可以被分割成一个或多个模块/单元,所述一个或者多个模块/单元被存储在所述存储器61中,并由所述处理器60执行,以完成本申请。所述一个或多个模块/单元可以是能够完成特定功能的一系列计算机程序指令段,该指令段用于描述所述计算机程序62在所述终端设备6中的执行过程。例如,所述计算机程序62可以被分割成获取模块、存储模块、处理模块。
所述获取模块,用于获取分配的存储空间,所述存储空间包括至少两个存储块,每个存储块包括至少两个存储页,每个存储页的大小相等;
所述存储模块,用于将获取的每条待存储数据依次写入所述存储空间的存储页中,所述存储空间中写入的数据形成数据队列;
所述处理模块,用于基于所述存储空间中写入的数据队列进行数据处理,所述数据处理包括:循环追加写入处理、标记式删除处理、开机检索整理处理、缓冲索引读取处理。
其它模块或者单元可参照图5所示的实施例中的描述,在此不再赘述。
所述终端设备包括但不仅限于处理器60、存储器61。本领域技术人员可以理解,图6仅仅是终端设备6的一个示例,并不构成对终端设备6的限定,可以包括比图示更多或更少的部件,或者组合某些部件,或者不同的部件,例如所述终端设备还可以包括输入设备、输出设备、网络接入设备、总线等。
所述处理器60可以是中央处理单元(centralprocessingunit,cpu),还可以是其他通用处理器、数字信号处理器(digitalsignalprocessor,dsp)、专用集成电路(applicationspecificintegratedcircuit,asic)、现成可编程门阵列(field-programmablegatearray,fpga)或者其他可编程逻辑器件、分立门或者晶体管逻辑器件、分立硬件组件等。通用处理器可以是微处理器或者该处理器也可以是任何常规的处理器等。
所述存储器61可以是所述终端设备6的内部存储单元,例如终端设备6的硬盘或内存。所述存储器61也可以是所述终端设备6的外部存储设备,例如所述终端设备6上配备的插接式硬盘,智能存储卡(smartmediacard,smc),安全数字(securedigital,sd)卡,闪存卡(flashcard)等。进一步地,所述存储器61还可以既包括所述终端设备6的内部存储单元也包括外部存储设备。所述存储器61用于存储所述计算机程序以及所述终端设备所需的其他程序和数据。所述存储器61还可以用于暂时地存储已经输出或者将要输出的数据。
在上述实施例中,对各个实施例的描述都各有侧重,某个实施例中没有详述或记载的部分,可以参见其它实施例的相关描述。
本领域普通技术人员可以意识到,结合本文中所公开的实施例描述的各示例的单元及算法步骤,能够以电子硬件、或者计算机软件和电子硬件的结合来实现。这些功能究竟以硬件还是软件方式来执行,取决于技术方案的特定应用和设计约束条件。专业技术人员可以对每个特定的应用来使用不同方法来实现所描述的功能,但是这种实现不应认为超出本申请的范围。
在本申请所提供的实施例中,应该理解到,所揭露的终端设备和方法,可以通过其它的方式实现。例如,以上所描述的终端设备实施例仅仅是示意性的,例如,所述模块或单元的划分,仅仅为一种逻辑功能划分,实际实现时可以有另外的划分方式,例如多个单元或组件可以结合或者可以集成到另一个系统,或一些特征可以忽略,或不执行。另一点,所显示或讨论的相互之间的耦合或直接耦合或通讯连接可以是通过一些接口,装置或单元的间接耦合或通讯连接,可以是电性,机械或其它的形式。
所述作为分离部件说明的单元可以是或者也可以不是物理上分开的,作为单元显示的部件可以是或者也可以不是物理单元,即可以位于一个地方,或者也可以分布到多个网络单元上。可以根据实际的需要选择其中的部分或者全部单元来实现本实施例方案的目的。
另外,在本申请各个实施例中的各功能单元可以集成在一个处理单元中,也可以是各个单元单独物理存在,也可以两个或两个以上单元集成在一个单元中。上述集成的单元既可以采用硬件的形式实现,也可以采用软件功能单元的形式实现。
所述集成的模块/单元如果以软件功能单元的形式实现并作为独立的产品销售或使用时,可以存储在一个计算机可读取存储介质中。基于这样的理解,本申请实现上述实施例方法中的全部或部分流程,也可以通过计算机程序来指令相关的硬件来完成,所述的计算机程序可存储于一计算机可读存储介质中,该计算机程序在被处理器执行时,可实现上述各个方法实施例的步骤。其中,所述计算机程序包括计算机程序代码,所述计算机程序代码可以为源代码形式、对象代码形式、可执行文件或某些中间形式等。所述计算机可读介质可以包括:能够携带所述计算机程序代码的任何实体或装置、记录介质、u盘、移动硬盘、磁碟、光盘、计算机存储器、只读存储器(rom,read-onlymemory)、随机存取存储器(ram,randomaccessmemory)、电载波信号、电信信号以及软件分发介质等。需要说明的是,所述计算机可读介质包含的内容可以根据司法管辖区内立法和专利实践的要求进行适当的增减,例如在某些司法管辖区,根据立法和专利实践,计算机可读介质不包括是电载波信号和电信信号。
以上所述实施例仅用以说明本申请的技术方案,而非对其限制;尽管参照前述实施例对本申请进行了详细的说明,本领域的普通技术人员应当理解:其依然可以对前述各实施例所记载的技术方案进行修改,或者对其中部分技术特征进行等同替换;而这些修改或者替换,并不使相应技术方案的本质脱离本申请各实施例技术方案的精神和范围,均应包含在本申请的保护范围之内。