">
1设计模式分析
软件架构的设计主要包括以下方面:系统构件的描述、构件之间的交互、指导构件交互的模式,以及施加在模式上的约束[3]。下文将详细讲解各方面的技术特点。设计模式的基本思想是,很好地理解问题域、支持设计元素的封装、并经过长期演化,得到一批可以有效的解决实际问题的“习惯用法”[4]。
2传统弊端
以往在软件体系结构设计中,设计者通常把功能性的实体放在首位,这类功能的结构块,即是系统的构件。以COACHDSP系统为例,不管是消息调度,还是拍摄,或是存储管理,都是构件的组成。在传统设计过程中,构件的组织不可谓不充分,问题在于各构件的耦合度太大,相互纠结。传统面向过程的编程思想热衷于将不可见的指令执行牢牢封装在可见的函数代码流中。因此,对用户进程的设计思路是采用嵌套循环的方式,在“接收———处理———等待”的消息响应循环中,嵌套进多个子消息响应循环,目的是保持事务流的可控性和程序结构的清晰。子循环近似于主循环,区别在于子循环是以“死守”的方式等待一个特定的消息,直到接收到指定的消息(或者出现预知的异常),才跳出循环。这种模式的优势是设计思路简单,功能模块划分清晰。但是弊端也是显而易见的,一方面在子循环中,设计者极易忽略某些消息,导致系统异常增多;再一方面,软件代码冗余,整个系统连接成一个难以分割的整块,层次不清,有可能陷入无穷嵌套循环,进而崩溃;另一方面,代码复用性差,后期维护困难。如图1所示。为了改变这种状态,功能模块可以以消息关联的方式进行交互。消息关联是一种很重要的构件交互关系。从图1可以看出,整个软件设计中都没有连接件的影子,所有的连接件功能被包含在构件的实现中,由此整个系统犹如一块铁饼般密不可分。解决的方法是把系统中功能件和消息传递部分进行独立设计,以单独的模块定义来规范它的实施过程。模式的约束一般包含以下内容:目的、动机、适用性、结构、参与者、协作、后果等[4]。以COACHDSP系统开发为例,每一个设计模式都有着复杂的工序和上下文环境。如果不能清晰地界定模式的工作范围,将会陷入以往软件设计时遇到过的重复查询的窠臼。如何合理规划、分解设计模式,是一个浩大的工程。但是,只要规范了模式的语义和约束,对设计者来说,细分工作只是水到渠成的事情。
3改进方法
为改进上述不足,笔者改造了现有的设计模式,提炼了一套新的设计模式的应用模型。新的设计模式划分成三大模块:调度器、分发器和任务流。通俗来讲,调度器好比人体的“中枢神经”,分发器好比少数起到桥梁作用的“外周神经”,任务流好比体内众多的功能“器官”,三者组合形成一个完整的行为体。
(1)消息中枢———调度器(Scheduler)
调度器在整个设计模式中是唯一的。它专职于接收消息,定义所有消息的响应协议,将接收到的消息转送到正确的处理单元。调度器以一个消息“接收———处理———等待”的无限循环,保持着用户进程对处理器的控制权。调度器只能在整个嵌入式系统的生命周期内中出现一次,否则即陷入无尽的嵌套循环,其后果是灾难性的,而传统的设计思路无法避开这一陷阱。调度器作为应用系统的“中枢神经”,对不同需求的开发项目都是固定不变的,这样既能保证代码的一致和复用,也保证了开发的连贯性、高效性和可重用性。调度器通过消息“钩子”机制与千变万化的任务流形成紧密对接,调度器接收到的消息,第一时间传递给任务流的响应函数,系统就能快速而准确理解和响应所有的实时消息了。
(2)特定消息的分发器(MessageDistributeMachine)
有一些中断产生的消息或者常见的、响应处理多变的消息,其响应操作可以从调度器中分离出来,既可以保证调度器的稳定和清晰度,也便于功能的模块化。这类模块称为特定消息的分发器,可看作是只服务于某个消息的调度器,是调度器的有益补充。与调度器的区别在于,它只响应单一的消息,而且,响应完即刻退出,将处理器控制权交还给调度器。分发器包含了该特定消息的定义和响应协议,消息“钩子”接口函数和自同步机制。分发器与任务流的区别在于,前者对消息的响应不会产生需要处理的底层消息,所有需要处理的底层消息的响应代码都应该封装在任务流中。分发器对消息的分解协议是由应用开发者自行制订的,合理而稳定的分解协议对项目的二次开发是非常有益的。分发器与任务流的联接采用回调函数方式,由任务流定义收到该消息后需执行何种指令。分发器与调度器一起组成了应用系统的“神经系统”。在实现上,分发器既使用调度器的消息“钩子”与之挂靠,也提供自已的消息“钩子”供任务流使用,在两者之间起到了一个承上启下的作用。针对诸如“定时器”消息,“自定义”消息,“按键”消息等众多使用广泛,应用复杂的消息,笔者分别设计多个分发器对它们进行管理。分发器的使用使应用系统“神经系统”层次清晰而分工明确。
(3)分工明确的任务流(TaskFlow)
任务流数量庞大,涵盖了应用系统的全部功能。通过功能细分和模块定义,一个复杂的DSP应用系统的事务流可以分解成一个或多个任务流。道理类似于将一个复杂的任务分解成若干细致、简单、可重复的小任务,这些小任务相互协作,各尽其能,完成复杂的功能操作。通过对任务流的挑选和排列,可以实现应用系统的功能裁剪。每个任务流有着类似的模块结构,但各自完成相应的任务,这些任务流通过复用和组装,可以组合出复杂的DSP功能流。
(4)三者的协作关系
从图2中可以看出,改造后的系统架构中各类构件层次分明,模块清晰。调度器分流消息,分发器解析特定的消息。任务流响应消息,驱动底层指令,三者之间的关系也简单明了。调度器从底层得到消息后,传递给与该消息挂靠的分发器或任务流,分发器和任务流在处理过程中适时地发送自定义消息,一方面可以完成自同步操作,另一方面也可以进行事务流的分解。三者与底层组成一个指令流的循环,也是整个系统中唯一的循环。同时,通过任务流的分解,系统简化了每一个消息的响应处理,提高了系统的实时性。
4实现与测试
4.1各模块详细设计与实现
在程序结构上,随着消息的传递,代码执行权由调度器传递给分发器,再由后者传递给任务流,当任务流执行完最后一条指令后,执行权回溯给调度器。
(1)调度器
调度器作为用户进程的第一层封装,在代码结构上必然有类似Windows进程的循环格式。在详细设计时,为提高消息响应的效率,消息和任务流之间的联接采用“挂靠———接收/响应———解挂”的消息“钩子”机制。调度器模块中含有各消息的回调函数指针变量,用于任务流等进行消息绑定。此外还有部分表征DSP全局状态的变量。该模块的程序流程如图3所示。
(2)分发器
分发器模块作为特定消息的解析单元,以提供消息的解析和服务为己任。不是所有的消息都会采用分发器来解析,只是针对定时器消息、按键消息、用户消息等在系统整个生命周期随时发生或者多次发生或者在不同情形下响应操作不同的消息而设计。并不直接影响应用方案的功能实现。因此一旦代码设计成型,这部分代码将不会再因方案中功能的增减而增删。通常的程序流程是分发器接受从调度器传来的消息及参数,优先执行任务流的回调函数(如果有的话),再执行默认处理。为了规范设计消息分发器模块,便于其模块化裁剪、组装和扩展。分发器模块拥有相同的数据结构。在具体设计时,为每一个分发器分配固定的全局地址,以简化调用过程,提高系统运行效率。特别地,用户自定义消息分发器要承担更多的作用。由于前文讲到的自定义消息的特点,自定义消息可以实现用户进程的自同步,任务流的转换以及操作流的分解,减少系统对单个消息的响应时间,提高代码的复用率。因此分发器中,对用户自定义消息的分解是重中之重。虽然用户消息只有256种不同的参数,但也足够应付DSP等大、中型应用系统了。除了应用到上述地方外,用户自定义消息可用于分解人机界面代码,完善的分解协议结合全局变量作缓存,将完美地解决冗长而琐碎屏显代码的组织,达到代码精简和高效复用的效果。
(3)任务流
任务流实现DSP的具体功能,处理流程不一而足,以完成一个完整的不可细分的功能流程为标准进行切割和组装。任务流之间的流转由当前任务流发起,方法是在退出前发送一条启动下一个任务流的用户消息。任务流拥有统一的数据结构,其中包含有任务流编号(必须)、启动(必须)、退出(可选)、消息分发器回调函数(可选)。一个庞大的任务流地址映射表记录了所有任务流的编号及对应的结构体地址,专用于任务流的上下文切换。在实际应用设计时,根据项目需求的变化,设计者可以随意裁剪任务流的数量和次序,轻松实现系统功能的增减。
4.2仿真测试
为阐述设计模式的界分和内在组织,笔者以一个典型的应用功能———拍摄加以佐证:用户对准目标按下“快门”键,拍下照片,相片将保存在存储卡上,完成存储后,相机回复拍摄前的预览状态。第一步:用户按下“快门”键,底层硬件产生一个“HM_FD_GPIO_BUTTON_NOTIFICATION”消息,经调度器反馈到按键消息分发器解析。按键分发器向调度器反馈一个的自同步用户消息“MSG_TF_CAP_PHOTO”,标识待续的任务流为“拍摄”。第二步:自同步消息经过消息队列,由调度器转发,分发器启动“拍摄”任务流。后者驱动底层。第三步:底层完成所有功能操作后(其间产生的底层同步消息由任务流响应,图中省略),发出同步消息,当前任务流接收到消息后注销退出。笔者将这一设计思想在PC机上进行了仿真试验。以两个Windows进程摸拟DSP的用户进程和主机进程,两个进程间采用消息和消息队列的方式进行通信模拟。由于PC模拟实验的实现细节与本文主旨不符,此处不再细述。
5结语
新的设计模式结构清晰而流畅,在功能模块化和代码复用度方面得到了极大的改善,提高了嵌入式软件应用开发效率,为其他嵌入式系统设计模式实践提供了有益参考。本文为应用开发的框架设计提供了详细的介绍,对功能模块的分解、界定工作也给出了指导方法。然而,人机界面(UI)设计一直都是应用开发者的重点和难点。如何将此设计模式思想应用到UI设计实践,以及完美实现仿真器等,都需要进一步努力。
作者:栗华山 李东 单位:华南理工大学南校区计算中心