一般状况下,在嵌入式体系中完成数据办理咱们常选用嵌入式数据库。可是现在常用的嵌入式数据库(如SQLite、Berkeley DB等)均需嵌入式操作体系的支撑,且对嵌入式体系的内存、CPU处理速度等有较高要求,只能运用在比较高端的嵌入式体系中。在低端的嵌入式体系中,传统的数据办理办法是对数据存储空间按次序编号,数据存储与删去均依据编号次序操作。这种办法在屡次删去后会呈现许多存储空间碎片,一方面加大了程序查找闲暇存储空间的难度,数据办理操作时刻长(相似微机体系中硬盘长期不做磁盘碎片整理睬形成程序运转变慢的状况),另一方面或许形成存储空间运用率下降。本文提出了一种运用μC/OS使命调度算法完成的数据办理办法,该办法无需嵌入式操作体系的支撑,可运用于低端的嵌入式体系中,并且能够有用战胜低端嵌入式运用中传统数据办理办法的缺点。
1μC/OS使命调度算法
μC/OS是一种占先式的多使命嵌入式操作体系,它能够办理多达64个使命。μC/OS中,每个使命的优先级不一样且是仅有的,优先级最高的使命一旦准备安排妥当,则具有CPU一切权并开端投入运转。所以,μC/OS的使命调度算法的基本思想便是,查找当时准备安排妥当的最高优先级的使命,并进行使命切换。完成上述使命调度算法首要包括两个过程:确认现在哪几个使命处于安排妥当态,确认现在处于安排妥当态的使命中哪个优先级最高。为此,μC/OS供给了两个全局变量OSRdyTbl[]和OSRdyGrp。OSRdyTbl[]数组是使命安排妥当表,包括 8个字节(共64位),相当于把64个使命分为8组,每组8个使命,这64位数据的0、1状况别离代表64个使命是否处于安排妥当态(0代表闲暇,1代表安排妥当);OSRdyGrp为1个字节数据(8位),每一位的0、1状况别离代表OSRdyTbl[]数组的相应字节是否非零(即该组中是否有使命处于安排妥当态)。经过这两个全局变量的赋值就可完成使命安排妥当态与闲暇态的切换,这是μC/OS完成使命调度的根底。
1.1使使命进入安排妥当态
μC/OS经过OSRdyTbl[]和OSRdyGrp某方位“1”,使相应使命进入安排妥当态,如图1所示。
图1使命安排妥当表
假定优先级为12的使命进入安排妥当状况,12 = 1100b,则OSRdyTbl[1]的第4方位1,且OSRdyGrp的第1方位1(代表第1组有使命处于安排妥当态),相应的数学表达式为:
OSRdyGrp|=0x02;
OSRdyTbl[1]|=0x10;
则μC/OS在履行使命调度时,经过OSRdyGrp的值即可判别出第1组使命中有使命处于安排妥当态,然后再经过OSRdyTbl[]数组的第1个字节即可判别出此刻优先级为12的使命处于安排妥当态,则可做使命切换。
从上面的核算能够得到:若OSRdyGrp及OSRdyTbl[]的第n方位1,则应该把OSRdyGrp及OSRdyTbl[]的值与2n相或。为了核算便利,μC/OS中把2n的8个值(n=0~7)先核算好,存在数组OSMapTbl[]中,即:
OSMapTbl[0]=20=0x01(0000 0001)
OSMapTbl[1]=21=0x02(0000 0010)
……
OSMapTbl[7] = 27=0x80(1000 0000)
μC/OS中,优先级数分解为高3位和低3位,高3位代表使命组号,低3位代表使命在地点组中的方位。则恣意优先级为prio的使命进入安排妥当态只需履行以下程序:
OSRdyGrp|=OSMapTbl[prio 》 3];
OSRdyTbl[prio》3]|=OSMapTbl[prio & 0x07];
1.2使使命进入闲暇态
μC/OS经过使命安排妥当表OSRdyTbl[prio》3](prio代表使命优先级)中相应位清零使相应使命进入闲暇态,当OSRdyTbl[prio》3]中的一切位都为零时,还需将OSRdyGrp的相应位清零,代表全组使命中没有一个使命进入安排妥当态。
1.3查找当时处于安排妥当态的最高优先级使命
μC/OS选用查表法查找当时处于安排妥当态的最高优先级使命,它预先界说了数组OSUnMapTbl[]作为查找表,如下:
INT8U cONST OSUnMapTbl[]={
0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
};
相应的查找程序如下:
High3=OSUnMapTbl[OSRdyGrp];//优先级高3位,即当时处于安排妥当态的最高优先级的使命的组号
Low3=OSUnMapTbl[OSRdyTbl[High3]];//优先级低3位
prio=(Hign3《3)+Low3;//取得当时处于安排妥当态的最高优先级的使命
例如:若OSRdyGrp的值为01101000b,则查得OSUnMapTbl[OSRdyGrp]的值是3,它对应于OSRdyGrp中的第3方位1(即当时处于安排妥当态的最高优先级使命处于第1组使命中);若OSRdyTbl[3]的值是11100100b,则查OSUnMapTbl[OSRdyTbl[3]]的值是2,则进入安排妥当态的最高使命的优先级prio=3×8+2=26。
从上文的核算可看出μC/OS查找当时最高优先级使命所*的时刻为常数,与运用程序中树立的使命数无关,这个特性是本文完成新式嵌入式数据办理的要害。
2运用μC/OS使命调度算法完成嵌入式
数据办理在低端的嵌入式运用中,数据办理的首要功用便是数据存储与数据删去。传统的做法是对数据存储空间按地址次序编号,数据存储与删去均依据编号操作,每个编号的存储空间还供给了标志位,用于判别该空间是否已被占用。这种办法有一个很大的坏处:屡次删去后会呈现存储空间碎片,这形成后续操作中查找闲暇空间耗时较长,且存储量越大,这个现象越严峻,大大下降了数据办理操作的功率。有些程序员为了处理这个坏处对删去操作只供给删去一切记载的功用,不供给独自删去某个记载的功用,但这明显献身了产品的易用性。本文运用μC/OS使命调度算法完成嵌入式数据办理,可有用处理以上问题。
2.1基本思想
运用μC/OS使命调度算法完成嵌入式数据办理的基本思想是:将μC/OS中的“使命优先级”与数据办理的“记载号”对应,将“使命安排妥当态”与“存储空间空状况”(留意,不是存储空间满状况)对应,将“使命闲暇态”与“存储空间满状况”对应,将“使使命进入安排妥当态”与“数据删去”对应,将“使使命进入闲暇态”与“数据存储”对应,将“查找当时处于安排妥当态的最高优先级使命”与“查找当时闲暇存储空间”对应。即在实践运用中,数据存储前先依据μC/OS中的“查找当时处于安排妥当态的最高优先级使命”的办法查找现在优先级最高的闲暇存储空间,取得相应记载号,然后在数据存储后依据μC/OS中的“使使命进入闲暇态”的办法使相应记载的存储空间置为“满”状况;数据删去后依据μC/OS中的“使使命进入安排妥当态”的办法使相应记载的存储空间置为“空”状况。明显,该办法较传统办法有两大长处:查找闲暇存储空间的速度远高于传统办法,且查找时刻为常数,即查找时刻与记载数无关(传统办法的查找时刻随记载数递加);不会呈现存储空间碎片,由于本办法按优先级存储数据,删去的存储空间的优先级必定高于未运用的存储空间,则在后续存储操作中会将其优先用于存储,然后也就避免了存储空间碎片的呈现。
2.2算法的改善
μC/OS的最大使命数为64,这意味着直接选用μC/OS使命调度算法完成的数据办理的最大记载数也仅为64个,这明显不适用于大都运用场合,因而需对算法进行改善。本办法引进“页”的概念,即每64个记载为1页,数据存储前先查找包括空记载的页号,然后在该页中查找空记载。查找包括空记载的页号的办法与查找空记载的办法相同(即都依据μC/OS中的“查找当时处于安排妥当态的最高优先级使命”的办法查找),因而最大记载数为64记载/页×64页=4096个记载。依此类推,可持续扩展存储记载数。为了了解便利,下文代表记载闲暇状况和页内记载号的全局变量界说为OSRdyTbl[64][8]、OSRdyGrp[64]和prio,代表页闲暇状况和页号的全局变量界说为OSRdyPage、OSRdyPageTbl[8]和PrioPage,代表记载在整个存储空间的序号界说为RecordNo(则RecordNo = PrioPage×64+prio)。
2.3嵌入式数据办理首要过程的完成
2.3.1数据初始化
在嵌入式体系刚运转时,一切记载应为空状况,因而需将代表记载闲暇状况和页闲暇状况的全局变量OSRdyTbl[]、OSRdyGrp、OSRdyPageTbl[]和OSRdyPage的一切字节均初始化为0xff(由于“1”代表闲暇)。
2.3.2数据存储
数据存储前先要找到优先级最高的空记载,其流程为先找到含空记载的页号,然后在该页中查找空记载号,最终依据页号和空记载号核算出当时可用于存储且优先级最高的存储空间的序号。具体程序如下:
High3=OSUnMapTbl[OSRdyPageGrp];//高3位
Low3=OSUnMapTbl[OSRdyPageTbl][High3]];//低3位
PrioPage=(High3《3)+Low3;//先找到含空记载的页号
High3=OSUnMapTbl[OSRdyGrp[PrioPage]];
Low3=OSUnMapTbl[OSRdyTbl[PrioPage][High3]];
prio=(High3《3)+Low3;//取得页中的空记载号
RecordNo=PrioPage*64+prio;//取有空记载在整个存储空间中的序号