摘要:从进程和线程调度的视点动身,介绍了一种规范化的实时多使命体系软件规划办法,提出了“前向分支”的规划准则,给出了完好的体系模型。
关键词:线程拆分 前向分支 实时多使命 单片机
在机电产品研制开发中,常常要涉及到依据嵌入式体系或依据单片机体系的程序规划。实时多使命是这类体系最依据的要求之一。在实践中一般选用以下两种处理计划:
一是在商业化时操作体系的根底上进行二次开发;二是用户主动规划体系软件。前者规划作业量小,规划周期短,体系的规划质量也简单得到确保。但因为商业实时操作体系往往较多地考虑通用性,短少灵敏性,关于一些特定的使用场合,其功用往往不能令人满意。一起,这种计划还存在着本钱高,依赖于特定硬件等缺陷。第二种计划能够从体系的实践要求和硬件的实践情况动身灵敏地进行体系规划,易于满意一些特定场合的功用要求,本钱也较低。可是,因为短少体系化、规范化的规划办法,短少高层次笼统东西,使得体系的规划质量不简单得到确保,你严峻地依赖于程序员的水平缓经历。
本文针对上述第三种计划的高限,从进程和线程调度的视点动身,介绍了一种体系化、规范化和易于工程化施行的实时多使命体系软件规划办法,提出了“前向分支”的规划准则,并给出了完好的体系模型。
1 进程的区分
对杂乱的体系需求进行模块化和层次化的区分是软件规划的根本办法。在实践中杂乱的体系需求一般被区分为一些功用相对独立的使命模块,每个使命模块被视作一个进程(process)。体系中如有多个进程并发(concurrent)运转,该体系便是一个多使命的体系。在图1所示的比如中,n个使命模块构成了微观上并发运转的一组进程(即Proc_1~Proc-n)。Proc_5和 Proc_9是两个具有代表性的进程结构。Proc_5是断续进行的进程,表明了某一次序逻辑操控的流程。Proc_9是LCD汉字显现程序,其结构是典型的多重循环。其功用是将数组aDisplay中所描绘的24×24点阵中文字符串送至LCD显现屏。ADisplay的结构参几图3(e)。
Proc_9 的根本作业原理如下:当cDispiay不为0时,顺次从aDlsplay中取出每个待显现汉字的点阵方位及其在LCD内部显存中的地址,依据这两个参数将一个汉字的点阵次序发送到LCD内部显存中。直至悉数汉字显现完,cDisplay减为0,Proc_9转入空档状况,等候新的显现恳求。
体系程序的主要使命之一便是对进程进行调度,包括发动和停止进程、办理进程之间的通讯、处理进程之间的优先级等。可是假如按图1的结构次序调度进程、以进程为根本单位分配CPU时刻的话,明显存在严峻的问题。例如在Proc_5中,当程序处于等候K1闭合的状况时,其它任何进程都无法得到服务,特别当K1呈现毛病时,体系将处于“挂起”状况。假如一个进程过多地占有了CPU时刻,其他进程将不能得到公正、均匀的服务,呼应时刻无法得到确保,体系功率会下降。总归,只要将CPU时刻的分配单位减小,才干处理上述问题。
2 线程的拆分
线程(Thread)是CPU的根本履行单位。一个进程能够由一个或多个线程构成。如前所述,单一线程的进程可能会存在许多问题,而将一进程拆分为多个线程是处理上述问题的有用手法。由图1的Proc_5和Proc_9能够看出,一个进程过多地占有CPU时刻,是因为其间含有次数不确认的等候循环、纯延时和较为耗时的多重循环。其间,纯延时能够用软件延和中止守时两种办法完成,这两种办法在进程中又都能够归结为循环。因而,在拆分线程时应尽量遵从“前向分支”准则,使线程中不含有或少含有循环。
循环结构本质上是由一个分支判别和一个“反向”转跳构成的。所谓“前向分支”准则是指:在一次调度中,当程序产生雪支时,应使程序跳向一段未被履行过的代码,而不得重复运转已运转过的代码。假如严厉按“前向分支”准则拆分线程,循环结构将被彻底消除。图2和图3分别是Proc_5和Proc_9严厉按“前向分支”准则拆分为线程的成果。
假如进程规划遵从结构化程序思维,那么在对某一进程严厉按“前向分支”准则进行线程拆分时,最小拆分数量可按如下办法确认:进程进口至第一个循环回来节点之间如无程序代码,最小拆分数量等于循环回来节点数Nback;进程进口至第一个循环回来节点之间如有程序代码,最小拆分数量等于Nback+1。实践拆分数量能够大于最小拆分数量,但不该小于该数,
不然必定有一个以上的线程中含循环。两个循环回来节点之间(或进口到第一个循环回来节点之间、最终一个循环回来节点到出口之间)的代码就构成了一个线程的对待。假如原进程中无循环,可将该进程作为单一线程对等。在图1中,Proc_9中共有4个循环回来节点(①~④),Nback=4。按最小拆分数量拆分中循环回来节点数也为4,但其进口至第一个循环回来节点之间有代码,所以,Proc_5按最小拆分数量拆分为5个线程。
线程号变量tProc_n是体系中完成线程调度、在各相关线程间树立联络的中心。按“前向分支”准则进行线程拆分时,但凡遇到构成循环的“反向”分支时,就将该分支转向当时线程的出口,并在出口前为地点进程的线程号变量赋一新值指向要转去的线程。假如所要转去的线程与当时地点线程共同时,线程号变量赋值能够省掉。
在按“前向分支”准则规划的线程中,“结构上”的循环能够彻底消除,但进程规划中“逻辑上”的循环仍然是存在的,不然进程的原有功用将不能正确地完成。事实上,线程号变量中包括有“逻辑循环”的信息。只要在主循环中按图4的办法设度各线程就能够完成进程的“逻辑循环”。
为完成中止守时,Proc_5中设置了两个守时计数器cTimerAct_1和cTimerAct_2(以下称之为“动作守时器”),在发动守时器设置好其初值,由一个根底守时中止程序按必定的时刻距离(本例为1ms)减1。当动作守时器减为0时表明守时完毕。
关于持续运转的进程(如Proc_5),完毕使命时应将线程号为量指向恣意一个不必的空线程。为统一和便利起见,本文约好一切进程的0号线程均为空线程,进程完毕时线程号变量应置为0。