安全数字卡的存储检索方法
技术领域
本发明涉及数据处理技术,特别是涉及一种高速快效的SD(安全数字)卡存储检索方法技术。
背景技术
在电力自动化行业,有大量的监控数据需要存储。存储介质最早的是手工抄写到纸张上,后来随着计算机在电力自动化行业的应用,普遍使用软磁盘、U盘、硬盘等来存储数据,这些都是上位机在windows/unix等主流操作系统下实现的,后来随着单片机、DSP(数字信号处理器)等微处理器的蓬勃发展,电力自动化行业对监控系统的实时性和精确性提出了更高的要求,使得嵌入式操作系统在电力自动化行业得到迅速发送,随之而来的问题就是如何在嵌入式操作系统环境下解决大量数据的存储问题。最早人们常用的存储设备是EEPROM,需要用紫外线擦除,软件只能一次性的写入数据,如果要重新写入数据就必须再用紫外线擦除,这造成操作上非常大的不方便。后来人们开始使用FLASH,可以直接用软件擦写,但读写速度较慢;另外还有用各种RAM存储数据的,其读写速度快,但失电后存储的数据会丢失。再后来,高速FLASH出现了,兼有传统FLASH和RAM长度,但价钱太高。另外,这些存储设备都有个致命的缺陷:容量都无法做大,只能做到M级,已经不适合做现在大容量数据的存储。随着民用数码产品的高速发展,带来了新的存储设备SD卡(Secure Digital Card:安全数字卡),失电后存储的数据不会丢失,它的读写速度达到2MBPS,甚至更高,而容量很容易达到G级,是FLASH之类容量的数千倍,而价钱非常便宜,这就有可能使用SD卡代替传统的FLASH、RAM、硬盘等来存储监控系统的 大量数据。但由于电力自动化行业与民用数码产品行业不同,对数据的存储检索时间有很高的要求,所以在民用数码产品行业采用的SD卡存储检索方法是不能满足电力自动化行业的要求的。
SD卡是现在民用数码产品里广泛使用的存储设备,由于SD卡读写需要相应的一串指令,在2MBPS速度下读取SD卡信息,通过计算可知,读取1G字节SD卡数据大约需要60分钟的时间。用SD卡存储历史数据,需要检索历史数据时,普通的方法就是依次比较数据时间,极端的时候需要比较所有数据,那么需要60分钟,这么长的时间,是无法忍受的。为此,一般采用索引映射的方法,把SD卡分成2部分,前面为索引区,后面为数据区,索引区记录数据区的时间等信息,这样检索数据就变成了检索索引区,此方法显然能提高SD卡检索时间,但是,对大容量SD卡,搜索索引区仍然需要很长的时间,尤其在电力自动化行业,对数据响应的时间一般要求不大于1秒,此方法仍然无法满足要求。
发明内容
针对上述现有技术中存在的缺陷,本发明所要解决的技术问题是提供一种高速度、低成本、大容量、数据响应时间短的SD卡的存储检索方法。
为了解决上述技术问题,本发明所提供的一种SD卡的存储检索方法,其特征在于,检索方法的步骤包括:
1)建立数据结构,所述SD卡为设有m个扇区的SD卡,每个扇区为X(X≥512)字节,设扇区的前2n字节存储的内容是ID号,后X-2n字节存储的内容是数据,n为2-4;
2)对采样数据编码(预处理),并按序存入,设时间基准点Ti,则数据采样时间至时间基准点Ti的时间间隔为Ty(毫秒),采样数据以固定间隔时间Kj(毫秒)按照扇区的顺序和扇区内的数据点顺序依次存入;
3)进行数据点位置的计算,设基准数据点为O,其位置在第Fo扇区的第Qo点处;设要检索的数据点为X,其位置在第Fx扇区的第Qx点处;则计算如下:
a)先计算时间间隔Ts=|To-Tx|(毫秒),其中,To为基准数据点的(采样)数据时间(毫秒),Tx为要检索数据点的(采样)数据时间(毫秒);
b)再计算存储记录的时间间隔为:Ts′=|To-Tx|-P(Ts),其中P(Ts)为修正值,当步骤2)中采样数据编码为按序存入时P(Ts)=0;
c)数据点间隔Qs=Ts’/Kj,其中,Kj为采样数据的间隔时间(毫秒);
d)扇区间隔Fs为(Qs-Qo)/H的整数商,其中,Qo为基准数据点在扇区的位置,H为每个扇区保存的数据点个数;
e)要检索的数据点保存的扇区Fx=(Fd+Fo-Fs)取模,其中,Fd为SD卡的扇区总数,Fo为基准数据点保存的扇区;
f)要检索的数据点在扇区的位置Qx为H减去(Qs-Qo)/H的余数;
4)直接从数据点位置读取数据。
进一步的,所述步骤2)中的时间基准点为1970年1月1号0点0分0毫秒。
进一步的,所述步骤3)中设基准数据点为当前数据点,也就是最后一次写入SD卡的采样数据的位置。
进一步的,所述步骤3)b)中P(Ts)为Ts的分段(修正值)函数,P(Ts)由存储(停电或其它原因而停止运行存储的)记录确定,或根据二分法、快速逼近法搜索、计算得到。
利用本发明提供的SD卡的存储检索方法,由于采用按序存储的数据结构,使存储数据的检索过程变为存储数据的位置的计算过程,从数据点存储位置直接读取数据,所以检索速度比传统检索方法快得多;由于采用扇区设ID号的结构,从而对不连续的采样数据仍然可以快速检索。
具体实施方式
以下对本发明的实施例作进一步详细描述,但本实施例并不用于限制本发明,凡是采用本发明的相似方法及其相似变化,均应列入本发明的保护范围。
本发明实施例所提供的一种SD卡的存储检索方法。本发明通过对SD卡扇区合理的编码,无须索引区,就能快速检索历史数据。在电力自动化行业,保存历史数据都要求记录最近若干时间的数据,比如,最近1年的数据,有明显的特征:数据具有先进先出的特点,总是用最新的数据覆盖最老的数据。本发明记录数据方法如下:SD卡一般是以512字节为一个扇区,定义其前4字节为ID号,后508字节为数据空间(如果是2048字节或其它字节为一个扇区,方法一样)。ID号从1开始,依次增加。每写一个扇区,该扇区的ID号都比上次写的扇区的ID号大1。系统第一次写SD卡时,第一个扇区的ID号从1开始,第二个扇区的ID号为2,由此类推,假设为1G字节的SD卡,则第一次写到最后一个扇区是它的ID号为2048000,此时继续记录数据,按照先进先出的原则,应该接着写第一个扇区,此时ID号继续增长为2048001,然后接着写第二个扇区的ID号为2048002,如此一直循环写下去。要保存的数据假设是每0。1秒记录一次,那么4字节的ID号能保存的时间为:2的32次方乘以0.1秒,即429496727.6秒,大约13.6年。电力自动化行业对自动化装置的年限要求是10年,所以4字节的ID号可以保证在自动化装置的生命周期里ID号不会翻转(这里是假设每个扇区数据空间只记录一点的数据,如果每个扇区数据空间记录10点数据,则4字节ID号可用136年)。如果数据的采样密度更高,可以用6字节的ID号,甚至用8字节的ID号,存储方法都一样。数据空间可以为若干个采样点加第一个点或者最后一个点的采样时间,因为知道一个点采样的时间,根据位置顺序就可获得其它点的采样时间。当然,如果不在乎浪费一点空间,也可以每个点都带采样时间。为了进一步加快数据检索时间,数据的时间不用传统的年月日时分秒的方式来表示,而是采用相对于1970年1月1号0点0分0毫秒的毫秒数 来表示。因为年月日时分秒的方式记录时间,因为涉及闰年闰月大小月,每次比较时间都需要复杂的计算,而比较毫秒数就非常简单了,比较大小就行。
总之,本发明数据编码方法描述如下:以扇区为单位,每个扇区分为ID号、用毫秒数表示数据的采样时间、若干点采样数据共三部分。ID号从1开始依次增长,毫秒数是相对于1970年1月1号0点0分0毫秒的毫秒数。
本发明的数据检索方法非常简单,首先建立数据结构,所述SD卡为设有m个扇区的SD卡,每个扇区为X(512-2048)字节,设扇区的前2n(n为2-4)字节为ID号,后(X-2n)字节为数据(存储)空间;因为ID也具有连续性和时间性,既可以看作是时间的坐标,也可以看作是数据位置的坐标。假设当前数据点,也就是最后一次写入SD卡的采样数据,保存在第345(Fo)扇区处,ID号为12345678,数据时间To是1175587486300(毫秒)(也就是2007年4月3号8点4分46.3秒),那么如果要检索2007年3月31号12点0分0秒的数据,首先将要检索的时间Tx转换成1175342400000(毫秒),计算时间间隔Ts=To-Tx=1175587486300-1175342400000=245086300,仍然以采样间隔Kj为100毫秒为例,则当前数据点之前的第2450863(Qs)个点就是想检索的数据。假设每个扇区保存H=500个数据,当前点是当前扇区345(Fo)的第100(Qo)点,那么则要检索的数据点所在扇区与当前扇区的间隔Fs为(Qs-Qo)/H的整数商,即(2450863-100)/500的整数商=4901扇区,而要检索的数据点所在扇区的具体数据点Qx为H减去(Qs-Qo)/H的余数,即500-(2450863-100)%500=237点。而当前扇区为345(Fo)扇区,SD卡有2048000(Fd)个扇区,则要检索的数据点所在的实际扇区Fx为(Fd+Fo-Fs)取模,即(2048000+345-4901)取模=2043444。所以要检索的数据点为2043444(Fx)扇区的第237(Qx)点。上述例子说明了在已知当前数据点的位置的情况下,检索历史数据只需简单的计算就能得到需要数据位置,然后直接从数据点位置读取数据。
在本发明的实施例中,基准数据点也可以设首次写入SD卡的采样数据的位置为基准数据点0’;则计算如下:a)时间间隔Ts=Tx-To’(毫秒),其中,To’为基准数据点的(采样)数据时间(毫秒),Tx为要检索数据点的(采样)数据时间(毫秒);b)数据点间隔Qs=Ts/Kj,其中,Kj为采样间隔时间(毫秒);c)扇区间隔Fs为(Qs-Qo’)/H的整数商,其中,Qo’为基准数据点在扇区的位置,H为每个扇区保存的数据点个数;d)要检索的数据点保存的扇区Fx=(Fd+Fo’-Fs)取模,其中,Fd为SD卡的扇区总数,Fo’为基准数据点保存的扇区;e)要检索的数据点在扇区的位置Qx为H减去(Qs-Qo’)/H的余数;然后直接从数据点位置读取数据。
在实际应用中,有可能某段时间装置是停止运行的,这样就造成局部数据存储的不连续,如果只是简单根据当前点的时间和ID号计算出来的位置则有可能不是预期的数据。解决这个问题就是在计算时间间隔TS后用修正值修正,以修正数据存储不连续带来的误差,即在所述进行数据点位置的计算中,时间间隔为Ts=|To-Tx|,存储记录的时间间隔为:Ts′=|To-Tx|-P(Ts),其中P(Ts)为修正值:当采样数据编码始终按序存入时P=0;当数据存储不连续时,P为Ts的分段函数,即P(Ts);以所述例子为例:“假设当前数据点,也就是最后一次写入SD卡的采样数据,保存在第345(Fo)扇区处,ID号为12345678,数据时间To是1175587486300(毫秒)(也就是2007年4月3日8点4分46.3秒),那么如果要检索2007年3月31日12点0分0秒的数据,首先将要检索的时间Tx转换成1175342400000(毫秒),计算时间间隔Ts=To-Tx=1175587486300-1175342400000=245086300,”其中由于4月3日0点至1点装置停电1小时,则停止存储(记录)的时间间隔为3600000(毫秒),4月3日1点至4月3日8点4分46.3秒的时间间隔为TA=25486300(毫秒),因TS>TA,说明要检索的数据记录点在停止存储(记录)的时间段之前,则存储记录的时间间隔为:Ts′=|To-Tx|-P(TS)=245086300-3600000=219600000(毫秒),以后的关于数据点间隔Qs、要检索数据点所在的扇区Fx和所在扇区的具体数据点 Qx的计算同原实施例;分段函数P(Ts)可以从相关(停电或其它原因而停止运行存储的)记录中得到,也可根据二分法或快速逼近法搜索得到,具体说明如下:
如果装置从一开始就一直在持续运行,那当前数据点的位置自然是知道的,但在实际应用中,装置可能因为停电或其它原因而停止运行,当前数据点的位置如何获得?常见的方法就是用其它存储设备记录当前点位置,比如用SRAM或FLASH等,每往SD卡里写个采样点数据,就把扇区号和扇区内点号记在SRAM或FLASH的某个预先定义的位置。这样装置复位后直接读该信息就知道了当前数据点的位置。如果没有辅助的存储设备怎么办呢?这时就需要利用扇区ID号依次增长的特点,装置初始化时读第一个扇区ID号,根据二分法搜索,可快速找到ID号最大的扇区,也就是当前数据点的位置。仍然假设有2048000个扇区,运行一段时间后数据写满又从头开始写一段时间的数据,假设其存储的数据其ID号从0扇区依次为2048001、2048002、...3048000、1000001、1000002、...2048000.那么如何才能找到最新点,也就是3048000这个点呢?先读第一个扇区的ID号为2048001,再读1/2位置的扇区ID号为1024000,如果从第一个扇区到1/2位置扇区是连续的,则1/2位置的扇区ID号应该是2048001+2048000/2=3072001,所以若在1/2位置的扇区读到的ID号不小于3072001则说明最新点还在后面,继续读后面的1/2位置,即3/4位置扇区的ID号,同理分析最新点是否在后面,直到认为最新点不在后面为止。现实际读到的是1024000,说明最新点的位置在0与1/2位置范围里,再读前1/2的1/2位置,即1/4位置的ID号,为2560001,等于2048001+2048000/4,说明最新点在当前位置的后面,即1/4位置与1/2位置之间。再读其中间位置,即3/8位置的数据,同理根据此位置的ID号与上一次读的ID号连续与否,得出最新点在此位置的后面或前面,然后再读剩下区域中间点的ID号,直到最后还剩下1个点或2个点,如果扇区总个数是2的整数幂则正好最后剩下1个点即为最新点,否则可能会剩下2个点,此2个点中最大的为最新点。2048000介于2的20次方与2的21次方之间, 所以最多读22次即能找到最新点。用2分法找最大ID点方法归纳如下:定义扇区总数为d,F(x)为ID号最大的扇区,所有扇区依次定义为F(1)、F(2)、...F(x)...F(d),对应的ID号依次I(1)、I(2)...I(x)...I(d)。读扇区F(1)获得ID号I(1),读扇区F(d/2)获得ID号I(d/2),如果I(d/2)-I(1)大于等于d/2则说明扇区F(x)在扇区F(d/2)后面,否则扇区F(x)在扇区F(d/2)前面。如果I(d/2)-I(1)大于等于d/2则读F(d/2+(d-d/2)/2)即F(3d/4),若I(3d/4)-I(d/2)大于等于d/4,则说明扇区F(x)在扇区F(3d/4)后面,否则扇区F(x)在扇区F(3d/4)前面。如果I(d/2)-I(1)小于d/2则读F(d/4),若I(d/4)-I(1)大于等于d/4,则说明扇区F(x)在扇区F(d/4)后面,否则扇区F(x)在扇区F(d/4)前面。如此分析下去,每次缩小一半范围,则剩下最后1个或2个扇区就是F(x)。
在实际应用中,有可能某段时间装置是停止运行的,这样就造成局部数据不连续,如果只是简单根据当前点的时间和ID号计算出来的位置则有可能不是预期的数据。解决这个问题还是利用扇区ID号依次增长的特点,比较第一次计算出来的采样点数据的时间,根据与期望时间的时间差再计算一次,如果不对就继续计算,显然其计算次数与数据不连续的次数有关,实际工作中装置停电的次数非常少,数据不连续的现象很少,即使数据不连续的次数很多,此方法为快速逼近法,仍然可以快速找到目标数据。仍然以采样间隔为100毫秒每个扇区保存500个数据为例,假设根据当前点的时间和ID号计算出来的位置在扇区12345,如果该位置数据时间与要检索的时间早560000毫秒,560000/100/500=11.2,那么往后11个扇区读,即读12356扇区。如果扇区12345的数据比要检索的时间晚560000毫秒,那么往前11个扇区读,即读12334扇区。同理,再分析新读扇区的数据时间与要检索的时间间差,直到时间差小于500*100=50000毫秒为止,则要检索的数据就在最后读的那个扇区里。归纳如下,根据当前点的时间和ID号计算出来的位置用F(a)表示,该处 数据时间用t(a)表示,要检索的目标数据时间用t(x)表示,对应扇区仍然用F(x)表示,每个扇区有若干个数据点占用时间用T表示(如上例中每隔100毫秒采一点每个扇区500点则每个扇区占用时间50000毫秒),则根据F(a)、t(a)、t(x)、T求F(x)的方法如下:读F(a+(t(x)-t(a))/T),得到的数据时间为t(a+(t(x)-t(a))/T),为了表达式清晰用b表示a+(t(x)-t(a))/T,如果t(x)-t(b)小于等于T,则目标数据就在此扇区里,否则再读F(b+(t(x)-t(b)/T),看该处数据时间与t(x)的差是否小于等于T,如果大于T则继续按上述计算方法读新位置数据,直到其时间差小于等于T即找到目标数据为止。