首页 / 专利库 / 银行与财务事项 / 别名映射 / 独立主动构件和可运行主动构件组装模型及构件拆分方法

独立主动构件和可运行主动构件组装模型及构件拆分方法

阅读:1031发布:2020-06-28

专利汇可以提供独立主动构件和可运行主动构件组装模型及构件拆分方法专利检索,专利查询,专利分析的服务。并且本 发明 提供一种独立主动构件和可运行主动构件组装模型及构件拆分方法,独立主动构件组装模型为集合P={第1层主动构件、第2层主动构件子集合…第n层主动构件子集合},其中,n≥2;第n层主动构件子集合中的各主动构件基于第n层虚拟消息总线进行构件组装,得到第n-1层主动构件子集合中的单个主动构件;以此类推,直到第2层主动构件子集合中的各主动构件基于第2层虚拟消息总线进行构件组装,得到第1层主动构件;其中,各层各个主动构件符合相同的协议。能脱离具体应用环境,完成独立的构件功能。使得构件能够简洁、高效率地复用、重构、组合,使得整个构件系统具备高度复用性。,下面是独立主动构件和可运行主动构件组装模型及构件拆分方法专利的具体信息内容。

1.一种独立主动构件组装模型,其特征在于,所述独立主动构件组装模型为集合P={第1层主动构件、第2层主动构件子集合…第n层主动构件子集合},其中,n≥2;所述第n层主动构件子集合中的各主动构件基于第n层虚拟消息总线进行构件组装,得到第n-1层主动构件子集合中的单个主动构件;所述第n-1层主动构件子集合中的各主动构件基于第n-1层虚拟消息总线进行构件组装,得到第n-2层主动构件子集合中的单个主动构件;以此类推,直到所述第2层主动构件子集合中的各主动构件基于第2层虚拟消息总线进行构件组装,得到第1层主动构件;
其中,所述集合P中的各层各个所述主动构件符合相同的协议。
2.根据权利要求1所述的独立主动构件组装模型,其特征在于,所述集合P中第1层主动构件到第n层主动构件子集合中的各个主动构件分别包括:所述虚拟消息总线、接口算子ID映射表、别名链接表以及一个以上的算子;其中,所述接口算子ID映射表用于存储接口算子ID与入口函数的对应关系;所述别名链接表用于存储引用算子ID与所述接口算子ID的对应关系;其中,所述接口算子ID为所述主动构件自身的算子标识;所述引用算子ID为挂接在虚拟消息总线上的主动构件内部的算子标识。
3.根据权利要求2所述的独立主动构件组装模型,其特征在于,所述第n层主动构件子集合中的各主动构件基于第n层虚拟消息总线进行构件组装,得到第n-1层主动构件子集合中的单个主动构件具体为:
所述第n层主动构件子集合中的各主动构件分别包括第n层虚拟消息总线、第n层接口算子ID映射表、第n层别名链接表以及一个以上的第n层算子;进行构件组装后得到的第n-1层主动构件子集合中的单个主动构件包括第n-1层虚拟消息总线、第n-1层接口算子ID映射表、第n-1层别名链接表以及一个以上的第n-1层算子;
在进行构件组装时,将各个所述第n层虚拟消息总线进行总线融合,得到第n-1层虚拟消息总线;将各个所述第n层接口算子ID映射表进行表格融合,得到第n-1层接口算子ID映射表;将各个所述第n层别名链接表进行表格融合,得到第n-1层别名链接表;将各个所述第n层算子进行融合,得到第n-1层算子;其中,n≥3。
4.根据权利要求2所述的独立主动构件组装模型,其特征在于,所述第2层主动构件子集合中的各主动构件基于第2层虚拟消息总线进行构件组装,得到第1层主动构件具体为:
所述第2层主动构件子集合中的各主动构件分别包括第2层虚拟消息总线、第2层接口算子ID映射表、第2层别名链接表以及一个以上的第2层算子;所述第1层主动构件包括第1层虚拟消息总线、第1层接口算子ID映射表、第1层别名链接表以及一个以上的第
1层算子;
在进行构件组装时,将各个所述第2层虚拟消息总线进行总线融合,得到第1层虚拟消息总线;将各个所述第2层接口算子ID映射表进行表格融合,得到第1层接口算子ID映射表;将各个所述第2层别名链接表进行表格融合,得到第1层别名链接表;将各个所述第2层算子进行融合,得到第1层算子。
5.根据权利要求2所述的独立主动构件组装模型,其特征在于,所述别名链接表存储的所述引用算子ID与所述接口算子ID的对应关系为等值映射关系。
6.根据权利要求1所述的独立主动构件组装模型,其特征在于,所述独立主动构件组装模型内置有协同并发式总线接口,所述协同并发式总线接口用于挂接到协同并发式总线上。
7.根据权利要求6所述的独立主动构件组装模型,其特征在于,所述协同并发式总线包括:信息获取模、并行环形分配器、线性内存块、消息填充模块、并行入队器、消息队列池、排队顺序管理器、入口映射表和系统堆栈;
其中,所述信息获取模块用于从接收到的待处理的外部并行的消息中获取目标算子ID以及消息长度值;其中,所述目标算子ID为处理所述消息的算子标识;同时用于获取附加管理消息的附加管理消息长度值,然后计算所述附加管理消息长度值与获取到的所述消息长度值的和,得到消息占用空间值;其中,所述附加管理消息长度值≥0;
所述并行环形分配器为非阻塞式并行的空间环形分配器,用于根据所述信息获取模块获取到的所述消息占用空间值,按环形划分原则连续动态的划割所述线性内存块,非阻塞式并行地得到与消息占用空间值相同的空白消息槽;
所述消息填充模块用于将所述消息及所述附加管理消息填充到所述并行环形分配器分配的所述空白消息槽,得到非空白消息槽;
所述并行入队器用于对所述空白消息槽或所述非空白消息槽进行非阻塞式并行入队操作;
所述消息队列池用于缓存尚未处理的已入队消息;
所述排队顺序管理器用于根据预设调度策略从所述消息队列池中选择需处理的指定消息,对所述指定消息进行协同的出队操作;
所述入口映射表,根据所述目标算子ID查找所述入口映射表,获得与所述目标算子ID对应的函数入口地址;根据所述函数入口地址以及所述指定消息的指定消息槽地址,调用对应的算子执行函数,从而处理出队的所述指定消息;
所述系统堆栈为所述协同并发式总线中所有算子共享的堆栈空间;各个算子所共享的系统堆栈空间相互覆盖,为重叠式,即非层叠式;
并且,所述协同并发式总线内的算子仅具有就绪状态,即使当所述协同并发式总线内不存在任何消息时,所述协同并发式总线内的算子仍处于就绪状态;一旦当所述协同并发式总线内到达消息时,且当该消息所对应的算子被调度时,被调度到的算子立即获得处理器。
8.根据权利要求7所述的独立主动构件组装模型,其特征在于,所述消息为定长消息或变长消息。
9.根据权利要求7所述的独立主动构件组装模型,其特征在于,当所述并行环形分配器在所述线性内存块的最末端划割空白消息槽时,如果所述线性内存块最末端剩余的空闲空间小于所述消息占用空间值,则直接舍弃所述最末端剩余的空闲空间,所述最末端剩余的空闲空间形成废弃槽。
10.根据权利要求7所述的独立主动构件组装模型,其特征在于,所述消息填充模块首先将所述消息及所述附加管理消息填充到所述并行环形分配器分配的所述空白消息槽,得到非空白消息槽;然后所述并行入队器对所述非空白消息槽进行非阻塞式并行入队操作具体为:
所述并行环形分配器配置有第一头指针和第一尾指针,当需要分配新的空白消息槽时,直接在当前位置的第一尾指针后面划出与所述消息占用空间值相同的空间,得到所述新的空白消息槽,然后再将所述第一尾指针非阻塞式并行移动到所述新的空白消息槽的尾部;
所述并行入队器配置有第二头指针和第二尾指针;通过非阻塞式并行移动所述第二尾指针实现对所述非空白消息槽进行非阻塞式并行入队操作;
其中,所述并行环形分配器配置的第一头指针和第一尾指针不同于所述并行入队器配置的第二头指针和第二尾指针。
11.根据权利要求7所述的独立主动构件组装模型,其特征在于,所述并行入队器首先对所述空白消息槽进行非阻塞式并行入队操作,然后所述消息填充模块再向入队的所述空白消息槽填充所述消息及所述附加管理消息具体为:
所述并行环形分配器与所述并行入队器共用相同的头指针和尾指针,当所述并行环形分配器从所述线性内存块中分配出空白消息槽的同时,该空白消息槽也被所述并行入队器执行了入队操作;然后所述消息填充模块再向入队的所述空白消息槽填充所述消息及所述附加管理消息。
12.根据权利要求11所述的独立主动构件组装模型,其特征在于,在抢先环境下,其中,抢先环境指:在多核处理器、或单核多处理器、或普通时间片式抢先调度时,主线程与其它线程能相互抢占,或同时并行交叉执行,这种软件执行环境,称之为抢先执行环境,简称为抢先环境;
在所述并行环形分配器从所述线性内存块中分配出空白消息槽之前,预先使所述空白消息槽处于休眠状态,其中,处于休眠状态的空白消息槽称为休眠消息槽;然后所述消息填充模块向所述休眠消息槽中填充所述消息及所述附加管理消息,当填充完成之后,所述休眠消息槽被激活时,即转变为活跃状态,其中,处于活跃状态的消息槽称为活跃消息槽;其中,休眠消息槽为不会被所述协同并发式总线调度给算子执行的消息槽;活跃消息槽为属于所述协同并发式总线正常调度范围的消息槽。
13.根据权利要求12所述的独立主动构件组装模型,其特征在于,采用变长消息时,通过消息槽中写入的消息长度参数是否为0区分所述休眠消息槽和活跃消息槽;当所述消息槽中写入的消息长度参数为0时,该消息槽为所述休眠消息槽;当所述消息槽中写入的消息长度参数不为0时,该消息槽为所述活跃消息槽。
14.根据权利要求7所述的独立主动构件组装模型,其特征在于,还包括:监控管理中心;所述监控管理中心用于对所述协同并发式总线内部的消息,进行集中监视、分析、控制、过滤和管理。
15.根据权利要求7所述的独立主动构件组装模型,其特征在于,还包括:空间回收模块;所述空间回收模块用于回收所述协同并发式总线内的出队后的消息本身以及所述消息槽。
16.根据权利要求7所述的独立主动构件组装模型,其特征在于,还包括:节电装置;所述节电装置用于:当所述协同并发式总线内不存在消息时,立即通知使用本协同并发式总线的应用系统进行节能调度。
17.一种基于权利要求1-16任一项所述独立主动构件组装模型的可运行主动构件组装模型,其特征在于,所述集合P中还包括第0层主动构件;所述第1层主动构件基于消息总线进行构件组装,得到所述第0层主动构件。
18.根据权利要求17所述的可运行主动构件组装模型,其特征在于,所述第0层主动构件包括:所述消息总线、第0层接口算子ID映射表、第0层别名链接表以及一个以上的第0层算子;所述第1层主动构件包括第1层虚拟消息总线、第1层接口算子ID映射表、第1层别名链接表以及一个以上的第1层算子;
所述第1层主动构件基于所述消息总线进行构件组装,得到所述第0层主动构件具体为:
在进行构件组装时,将所述第1层虚拟消息总线进行总线融合,得到所述消息总线;将所述第1层接口算子ID映射表进行表格融合,得到第0层接口算子ID映射表;将所述第1层别名链接表进行表格融合,得到第0层别名链接表;将所述第1层算子进行融合,得到第
0层算子。
19.一种对权利要求17-18任一项所述的可运行主动构件组装模型进行构件拆分方法,其特征在于,包括以下步骤:
预先设定构件拆分规则,当所述可运行主动构件组装模型满足所述构件拆分规则时,按所述构件拆分规则拆分所述可运行主动构件组装模型。
20.根据权利要求19所述的构件拆分方法,其特征在于,所述构件拆分规则为:当所述消息总线的调度程序由两个以上内核或处理器执行时,将所述消息总线分裂为与所述内核数量或所述处理器数量相同的分布式的对等的子总线;所述可运行主动构件组装模型中各层各个所述主动构件分别挂接到对应的所述子总线上;或者
所述构件拆分规则为:动态统计所述可运行主动构件组装模型中各个主动构件的负荷,根据预设的负载均衡原理,动态地将所述消息总线分裂为分布式的对等的多个子总线;
所述可运行主动构件组装模型中各层各个所述主动构件或算子分别挂接到对应的所述子总线上;或者
所述构件拆分规则为:动态统计所述可运行主动构件组装模型中各个主动构的能效比,根据预设的节能原理,动态地将所述消息总线分裂为分布式的对等的多个子总线;所述可运行主动构件组装模型中各层各个所述主动构件或算子分别挂接到对应的所述子总线上;或者
所述构件拆分规则为:动态统计所述可运行主动构件组装模型中各个主动构件的失效率,根据预设的可靠性原理,动态地将所述消息总线分裂为分布式的对等的多个子总线;所述可运行主动构件组装模型中各层各个所述主动构件或算子分别挂接到对应的所述子总线上。

说明书全文

独立主动构件和可运行主动构件组装模型及构件拆分方法

技术领域

[0001] 本发明属于计算机技术领域,具体涉及一种独立主动构件和可运行主动构件组装模型及构件拆分方法。

背景技术

[0002] 众所周知,软件设计的终极目标为:真实世界是什么样子,软件就应当设计成什么样子,从而实现通过软件模拟真实世界的目的。由于真实世界是纷繁复杂地,如实地模拟真实世界往往并不容易。前人经过多年的实践发现,软件系统对真实世界的每个细节模拟得越逼真,软件就越容易设计、理解与维护。由于面向对象编程真实地模拟了现实世界的事物,容易理解、方便维护、容易变更,因此,面向对象编程取代了面向过程编程,成为目前主流的编程方式。
[0003] 然而,由于硬件成本等多种因素的限制,在现实世界中,无处不在的、多个对象同时动作的“并行”活动,在单台计算机中,却极少能够真实模拟。现代计算机软件系统中,绝大部分都只呈现“伪并行”活动:从宏观上看,一台计算机能够同时执行多个任务、多个程序,若干对象同时在运行;但从微观上看,在任一瞬间、任一时刻,则只有一个程序在运行。由于处理器速度非常快,它在几个程序间来回快速切换,经过稍长一段时间,我们就觉得这几个程序是在同时执行、同时活动。这种现象,通常称之为“并发”,以区分严格意义上的“并行”活动。
[0004] 一般在操作系统等中低层软件中,提供相应的并发技术实现机制,并对外提供专的并发服务接口,以便上位程序能完成并发活动。上位应用程序,则调用这些并发服务接口,使自己呈现为一个或多个并发的任务。
[0005] 并发实体(任务、进程、线程、纤程等)间的调度操作(用于操作系统、软件总线等),提供了并发技术的实现机制。现代操作系统中,剥夺式调度是普遍采用的调度策略。但它具有若干致命弱点,试列举如下:
[0006] (1)堆栈空间问题:剥夺式调度随时可能打断并发实体的执行过程,因此需要保护与恢复并发实体运行环境(最少需要包含指令寄存器等),这需要RAM堆栈空间。在普通运行场合(如PC机),这个问题不突出。但在大量并发实体(如单片机在数千网络连接)的情况下,问题将变得相当突出;在RAM稀缺的特殊场合(如WSN应用)下,调度将变为不可行。
[0007] (2)执行效率问题:由于需要保护与恢复并发实体运行环境,这部分调代码的执行是必须增加的。在非常轻量级调度的情况(如TinyOS)下,相对于调度整体执行时间,它所增加的执行时间是非常可观的,严重影响了轻量级调度的执行效率。
[0008] (3)竞争共享问题:剥夺式调度随时可能打断并发实体的执行过程,因此,所有并发实体间共享的数据与资源,都成为被竞争的对象,变成临界资源。如果把所有的这些被竞争对象,都用临界区或其它统一的通用措施保护起来,那么系统的整体运行效率将会降低到不可接受的程度。如果精心设计共享结构,只采用通用措施保护部分对象,则在编程与维护代码时,稍不当心就会引发临界资源竞争导致的时序故障(这类故障还特别难以重现与定位),对编程人员与维护人员的职业素养要求将会提高很多,提高了设计与维护成本,降低了系统可靠性。特别是对于大量无规律的共享并发数据(如上百个不同的特殊线程),在编程实践中,一般开发人员都望而生畏,除非特别必要,均避而远之。
[0009] (4)竞争复用问题:前述为了效率提升而进行优化的数据共享设计,会带来代码复用性问题。由于针对项目的竞争环境,采用了针对性地消除竞争的共享数据保护代码,这些代码一般不具备普遍的通用性。即使对于其它非常相似的项目,也很有可能面对的是其它不同的数据竞争条件,因此,需要做出另外优化的数据共享设计,不能直接复用原来模
[0010] TinyOS是加州大学伯克利分校(UC Berkeley)为无线传感器网络WSN(Wireless Sensor Network)开发的微内核操作系统。TinyOS的两层调度方式为:任务调度与硬件事务调度。硬件事务调度由硬件中断激活,可抢占普通任务,主要用于高优先级的快速实时响应。它基本雷同于一般中断处理程序,稍有出入的地方在于:它可以向任务调度发送信号,激活普通任务;同时,还能利用nesC关键字async的异步能,直接调用进入到nesC构件系统中,调用构件中的命令处理函数,并给构件发送异步事件。
[0011] TinyOS的基本任务为无参数函数。任务调度采用协同式的先进先出(FIFO)算法,任务之间互不抢占,没有优先级之分。一旦一个任务获得了处理器,就一直运行到结束。一般用于对时间要求不高的应用,本质上是一种延迟计算DPC(Deferred Procedure Call)机制。TinyOS 2.x调度器可由用户定制与替换。
[0012] 如图1所示,TinyOS 2.x核心PCB为一个固定长度的字节数组,组成一个FIFO就绪任务队列、以及一个等待任务池。系统内的每个任务均由一个字节的任务ID表示,编号为0~255,其中255表示空任务NO_TASK:即任务不存在。因此,系统内最多可容纳255个有效任务。具体某个应用系统中的实际任务数,也即字节数组的实际长度,则在源代码编译期间,由编译器自动生成。
[0013] 该字节数组存放的是任务就绪标志。如果某任务ID没有收到事件,不需加入到FIFO就绪队列中,则存放NO_TASK标志,进入等待任务池。如果该任务ID有事件发生,激活进入就绪态,则该任务ID字节中存放的是下一个就绪任务,表示本ID已进入FIFO就绪任务队列,等待执行。
[0014] 激活任务ID并行入队时,采用阻塞式的临界区保护法。如果该ID已处于就绪态,则返回忙标志,否则从队尾加入到就绪队列。由于仅有一个字节的ID入队,因此临界区能高速通过,不太影响中断响应速度。这个算法可以避免一个ID多次入队的潜在问题:如果同一ID可占用多个字节位置,在某些情况下,可能会占满字节数组,导致其它任务无法入队而系统假死。
[0015] 就绪任务ID从队首出队时,同样采用阻塞式的临界区保护法。如果没有就绪任务,则发信号给节电装置,进入节电状态。否则,检索出该任务的入口地址,执行该任务。因为调度器中仅有任务ID,不存在附加参数,因此任务必须是无参数函数。同时,任务是协同式的,前面任务必须完全退出(此时堆栈为空)以后,才能执行下一任务。因此,所有的任务都共享同样的内存堆栈空间。
[0016] TinyOS 2.x所有基本任务均是无参数函数,每个基本任务仅固定分配一个字节的任务ID,该字节存放任务就绪标志,没有空间存放其它参数。所以,本质上它只是一个信号灯系统。相较于可附带若干参数的消息系统而言,有若干弱点,试列举如下:
[0017] (1)任务不能携带入口参数:任务退出执行后,堆栈清空,同时信号灯系统无法携带或保存参数。因此,限制了任务的适用范围。只能用额外的措施予以弥补。如:用任务实现的自计数模块。
[0018] (2)任务信息不能统一管理:由于信号灯系统无法携带参数,外部环境与各任务之间的信息交换方式,完全依赖于外部环境与各任务自行商定,没有统一规范化的表示手段。因此,对于外部环境与任务、任务与任务之间交换的信息,不能直接用统一的手段收集、监视、过滤、控制、管理。只能用额外的措施予以弥补。这对软件系统的调试、测试、控制等,都是极大的限制。
[0019] (3)主动消息不能完全表达:由于信号灯系统无法携带参数,信息交换方式需由环境与任务间另行商定,不是统一规范。发送出去的消息只能通知接收任务说有消息发生,但不能一次性完全表达完毕。因此,接收信息的任务需要依赖于特定的信息交换方式,采用拉(Pull)模式机制,通过函数调用方式,取回具体的信息内容。对于实现完全可复用模块、及完全透明的分布式计算系统,这是一个致命的限制(理由后述),很难弥补。
[0020] TinyOS 2.x在任务ID并行入队与串行出队时,均采用阻塞式的临界区保护法。由于仅有一个字节的ID入队,因此临界区能高速通过,不太影响中断响应速度与系统性能。这是由于它采用了非常简易的信号灯机制。如果根据系统需求,要换用成消息机制,除了公知的阻塞型同步的死、优先级倒置、中断不能加锁、临界区不能并发等问题以外,还存在有其它问题,试列出如下:
[0021] (1)实时性能问题:相较于单字节的任务ID,消息一般较长,入队、出队均需要较长时间,会导致临界区执行时间加长很多。在一般单片机系统中,临界区保护一般由关中断完成。这样,会导致系统中断响应速度变慢,影响系统实时性能,降低系统整体效率。
[0022] (2)硬件实现问题:在各处理器与各软件系统上,实现并行入队临界区保护的技术手段变化多端,不容易导出简洁、高效、统一的并行入队模型。因此,不容易用硬件实现关键操作、辅佐并行入队,无法提高执行效率或带来其它优势。
[0023] TinyOS 1.x以及一般通用操作系统,在其调度程序数据结构中,均直接保存任务函数的入口地址。当调度程序选中该任务、完成必要准备工作后,就直接跳到该地址,以执行任务代码。相对于采用任务ID、以及ID地址映射表的方式,有若干缺点,试列举如下:
[0024] (1)入口地址含义单一:不能蕴含其它有意义的信息(如静态优先级)。
[0025] (2)入口地址仅在单机内有意义:跨越计算机后,该地址没有任何意义。
[0026] 因此,对于要求完全透明的分布式并行任务计算,是一个致命的限制。
[0027] TinyOS 2.x使用一个字节的基本任务ID,使得调度内核简洁高效。但这限制了它所能容纳的最大任务数为255,对稍微大型、任务数更多的系统,无法容纳处理,影响系统伸缩性。
[0028] TinyOS 2.x使用一个字节的基本任务ID,兼作为FIFO就绪队列指针、以及任务就绪标志。这与其它绝大多数操作系统一样,都具备有存放于RAM内存中的非零长度的任务PCB表。具有若干弱点,试列举如下:
[0029] (1)执行效率问题:由于需要对任务PCB表进行各种操作(如把任务从等待态转为就绪态),这部分调度代码的执行是必须增加的。在非常轻量级调度的情况(如TinyOS)下,相对于调度整体执行时间,它所增加的执行时间是额外的、比较可观的,影响了轻量级调度的执行效率。
[0030] (2)硬件实现问题:在各处理器与各软件系统上,任务PCB表的内容、实现的技术、优化手段等各种措施千变万化,不容易导出简洁、高效、统一的并发技术实现模型。因此,不容易用硬件实现关键操作、辅佐并发的实现,无法提高执行效率或带来其它优势。
[0031] (3)空间占用问题:由于有存放在RAM内的任务PCB表,即便RAM使用量非常微小(如TinyOS 2.x本质上可以用单个BIT位表征任务的等待态、就绪态),在RAM内存稀缺的情况下(如WSN系统),如果存在成千上万的大量任务(案例后述),会导致系统无法实现并发调度过程,成为致命的技术缺陷,限制了该技术的适用范围。
[0032] 构建TinyOS系统时,用nesC语言写成构件,通过接口规范进行构件连接,并在程序编译期间,用函数调用的方式进行静态组装。因此,在本质上,其构件对外公布的是函数名(链接期有效)与函数地址(运行期有效)。与公布ID的构件方案对比,有不少弱点,试列举如下:
[0033] (1)模块模型不一致:TinyOS 2.x任务采用ID方案,而其构件采用地址方案。二者不一致,存在2种模型,导致其系统基本模块的模型复杂化。
[0034] (2)地址方案适应性弱:ID方案更容易跨语言、跨异质系统,普适性更好。
[0035] (3)地址方案难以动态适应:在代码运行期内,除非特别维护,函数地址已无从追踪。而预定义的ID构件方案,更容易进行代码的引用、更改、替换、维护,更容易实现单块或整体代码热升级。
[0036] (4)函数地址仅在单机内有意义:跨越计算机后,该地址没有任何意义。因此,对于要求完全透明的分布式并行任务计算,是一个致命的限制。
[0037] 目前的TinyOS系统、结构化编程、模块化编程、面向对象编程、构件化编程......等等各种技术,在用小模块链接组装成更大模块时,均采用函数调用的方式完成。这种方式有致命的缺陷,是在复杂软件系统中,导致软件模块难以复用的最核心问题之一。下面详细说明:
[0038] 为了叙述简便,借用两个术语,先简单说明下:
[0039] 拉(Pull)模式和推(Push)模式,这两个术语原本是用于表示互联网上的一种信息传播方式。拉(Pull),是指用户主动浏览网站信息,把信息从自己感兴趣的网站上(拉)取回来。推(Push),是指网站主动把消息发送(推)给某些特定的用户。
[0040] 一个模块,通过调用处于另外一个模块中的函数,获得了结果。这个函数调用,也即信息获取过程,类似于网上信息拉的过程,因此也称之为拉模式。如果一个模块是并发实体(线程等),给另外一个并发实体主动发送消息。这种发送消息的过程,类似于网上信息推送的过程,因此也称之为推模式。
[0041] 拉模式与推模式,最重大意义的区别在于:每次拉的时候,用户均需要指定拉取的对象、以及拉取(内容)的具体条件;而每次推的时候,不需要用户有任何动作(当然在此之前,需要做些一次性地工作,如预订等等)。
[0042] 参看图2,为采用拉模式工作的两个模块。D模块代表被调用模块,除了D模块之外的其他所有部分,是进行主动函数调用的模块。为了对调用过程进行分析,对上面的调用模块进行了功能等效的分解。
[0043] 图中,In表示模块所需要的输入参数(消息),Out表示模块所输出的信息(消息),F模块是该模块必须完成的核心功能,B模块是该模块完成的另外一部分功能。因此,从本质上说,F+B的功能是该模块存在的意义所在。
[0044] C模块代表直接函数调用,相当于汇编的CALL指令,之后CPU的执行权直接转到了D模块中。拉模式中,这是必须存在的环节。D模块需要一定的参数Pm。该参数经由A模块:即参数变换后得到,在C模块调用时,一并传给D模块。
[0045] A模块进行参数转换,主要是对输入参数In,结合其他变量1,进行参数格式转换、匹配等工作,得到C模块所必须的参数Pm、以及F模块所必须的参数Pc。
[0046] 在某些情况下,为了得到参数Pm与Pc,A模块中参数转换必须要得到另外一部分信息Pb。这部分信息Pb,必须在先完成一部分模块功能(B前置功能)的同时得到。因此,B模块的前置功能是一个可能不存在的非必然模块。但如果存在,则从A模块获得参数Pf,完成部分预定的模块功能,然后回馈信息Pb给A模块,同时,在F核心模块需要的情况下,把可能的参数P提供给F模块。
[0047] 从D模块的被调用函数返回的信息Od,联合有关变量2,被E模块信息整理后,变换成F模块能直接利用的参数Pr,传递给F核心功能模块。
[0048] F模块在得到参数Pc、Pr、P之后,完成核心功能,获得输出信息Out。
[0049] 参数Pc、Pm有可能与参数In完全相同,这样A模块可能就不需要存在。D模块进行被调用函数后返回的信息Od,有可能与参数Pr完全相同,这样E模块可能就不需要存在。C模块的函数调用是在拉模式中必须存在的环节。
[0050] 如前所述,对于调用模块来说,图中A模块中的参数变换、C模块中的函数调用与模块本身的功能毫无关系。纯粹是因为工作在拉模式下,为了获得信息Pr,而不得不放置其中的代码。从模块内聚度度观察,它们的存在,降低了调用模块的内聚度。B模块的前置功能,从纯粹代码复用与模块内聚的角度看,最好也能剥离出调用模块。E模块进行信息整理,某些情况下,为了满足接口需求,也可以保留,但最好也能剥离。从设计角度看,一般也应该存在另外某种解决方案,将B模块、E模块均剥离出去。这样,在不采用拉模式工作时,仅只剩下有F核心功能模块,作为调用模块的唯一代码。这样,就可达到模块的最高复用性与移植性。
[0051] 如图2所示,在拉模式中,最为致命的缺点是:不可分割、必须存在的C模块的函数调用(否则就不是拉模式了)。由于C模块必须明确列出函数名(或地址)与参数Pm,这部分代码必须嵌入在调用模块中。因此,在调用模块被移植、复用时,不得不考虑D模块对于调用模块的影响。为了解决这个影响,典型的存在3种方法:
[0052] (1)不分析、不修改调用模块及D模块代表的被调用模块,二者同时整体复用。
[0053] 这是最好的解决方案,移植复用代价最小,效率、可靠性最高。问题是,调用模块及D模块代表的被调用模块,一般存在有其它下级模块,除非把这所有的下级模块(也就是从调用模块开始的一棵子树),全部整体移植复用,否则还是要面临下级模块的改编与适应问题。同时,新项目的业务逻辑能否恰好完整地需要这一整棵子树,仍是一个大问题。这样,子树移植复用方案,适用范围就大大变窄,仅在非常类似的项目中才合适,不具普适性。
[0054] (2)不分析、不修改调用模块,仅模拟D模块的输入、输出、以及相应功能。
[0055] 这种方式实现相对比较简单,但也要熟悉D模块所涉及到的专业业务知识与模型。如果这个专业知识比较跨越的话,这本身就是一个不小的负担。
[0056] 同时,这个方案还有一个大麻烦是,留下一堆无用的废代码。浪费空间与时间,降低了代码的时空效率。在系统比较复杂、且对时空效率要求较高时,这个问题更显突出。极端情况下,往往会促使设计人员干脆另起炉灶、重新开发,不能利用现有的模块与代码。
[0057] (3)分析、修改调用模块,改变D模块的输入、输出、以及功能,或者干脆取消。
[0058] 这种实现比较复杂,需要详细了解并读懂A模块、B模块、C模块、E模块及整个调用模块的代码逻辑,必须透彻了解调用模块的专业业务知识与模型,以及,熟悉D模块所涉及到的专业业务知识与模型。如果这2个专业知识比较跨越的话,它就是一个不小的负担。同时,分析修改代码,还与原来的可复用性设计密切相关。以往设计不良的代码、或是经过多次勉强维护后的代码,会很混乱,复用性很差。往往会促使设计人员干脆另起炉灶、重新开发,不能利用现有的模块与代码。

发明内容

[0059] 针对现有技术存在的缺陷,本发明提供一种独立主动构件和可运行主动构件组装模型及构件拆分方法,能够有效克服现有“并发”实现技术的弱点,高效可靠地实现“并发”技术、并行编程,具有普适、廉价、高效、可靠、节能、复用、透明分布、微内核、内在支持对象技术等一系列优点。
[0060] 本发明采用的技术方案如下:
[0061] 本发明提供一种独立主动构件组装模型,所述独立主动构件组装模型为集合P={第1层主动构件、第2层主动构件子集合...第n层主动构件子集合},其中,n≥2;所述第n层主动构件子集合中的各主动构件基于第n层虚拟消息总线进行构件组装,得到第n-1层主动构件子集合中的单个主动构件;所述第n-1层主动构件子集合中的各主动构件基于第n-1层虚拟消息总线进行构件组装,得到第n-2层主动构件子集合中的单个主动构件;以此类推,直到所述第2层主动构件子集合中的各主动构件基于第2层虚拟消息总线进行构件组装,得到第1层主动构件;
[0062] 其中,所述集合P中的各层各个所述主动构件符合相同的协议。
[0063] 优选的,所述集合P中第1层主动构件到第n层主动构件子集合中的各个主动构件分别包括:所述虚拟消息总线、所述接口算子ID映射表、所述别名链接表以及一个以上的算子;其中,所述接口算子ID映射表用于存储接口算子ID与入口函数的对应关系;所述别名链接表用于存储引用算子ID与所述接口算子ID的对应关系;其中,所述接口算子ID为所述主动构件自身的算子标识;所述引用算子ID为挂接在消息总线上的主动构件内部的算子标识。
[0064] 优选的,所述第n层主动构件子集合中的各主动构件基于第n层虚拟消息总线进行构件组装,得到第n-1层主动构件子集合中的单个主动构件,其中,n≥3具体为:
[0065] 所述第n层主动构件子集合中的各主动构件分别包括第n层虚拟消息总线、第n层接口算子ID映射表、第n层别名链接表以及一个以上的第n层算子;进行构件组装后得到的第n-1层主动构件子集合中的单个主动构件包括第n-1层虚拟消息总线、第n-1层接口算子ID映射表、第n-1层别名链接表以及一个以上的第n-1层算子;
[0066] 在进行构件组装时,将各个所述第n层虚拟消息总线进行总线融合,得到第n-1层虚拟消息总线;将各个所述第n层接口算子ID映射表进行表格融合,得到第n-1层接口算子ID映射表;将各个所述第n层别名链接表进行表格融合,得到第n-1层别名链接表;将各个所述第n层算子进行融合,得到第n-1层算子。
[0067] 优选的,所述第2层主动构件子集合中的各主动构件基于第2层虚拟消息总线进行构件组装,得到第1层主动构件具体为:
[0068] 所述第2层主动构件子集合中的各主动构件分别包括第2层虚拟消息总线、第2层接口算子ID映射表、第2层别名链接表以及一个以上的第2层算子;所述第1层主动构件包括第1层虚拟消息总线、第1层接口算子ID映射表、第1层别名链接表以及一个以上的第1层算子;
[0069] 在进行构件组装时,将各个所述第2层虚拟消息总线进行总线融合,得到第1层虚拟消息总线;将各个所述第2层接口算子ID映射表进行表格融合,得到第1层接口算子ID映射表;将各个所述第2层别名链接表进行表格融合,得到第1层别名链接表;将各个所述第2层算子进行融合,得到第1层算子。
[0070] 优选的,所述别名链接表存储的所述引用算子ID与所述接口算子ID的对应关系为等值映射关系。
[0071] 优选的,所述独立主动构件组装模型内置有协同并发式总线接口,所述协同并发式总线接口用于挂接到协同并发式总线上。
[0072] 优选的,所述协同并发式总线包括:信息获取模块、并行环形分配器、线性内存块、消息填充模块、并行入队器、消息队列池、排队顺序管理器、入口映射表和系统堆栈;
[0073] 其中,所述信息获取模块用于从接收到的待处理的外部并行的消息中获取目标算子ID以及消息长度值;其中,所述目标算子ID为处理所述消息的算子标识;同时用于获取附加管理消息的附加管理消息长度值,然后计算所述附加管理消息长度值与获取到的所述消息长度值的和,得到消息占用空间值;其中,所述附加管理消息长度值≥0;
[0074] 所述并行环形分配器为非阻塞式并行的空间环形分配器,用于根据所述信息获取模块获取到的所述消息占用空间值,按环形划分原则连续动态的划割所述线性内存块,非阻塞式并行地得到与消息占用空间值相同的空白消息槽;
[0075] 所述消息填充模块用于将所述消息及所述附加管理消息填充到所述并行环形分配器分配的所述空白消息槽,得到非空白消息槽;
[0076] 所述并行入队器用于对所述空白消息槽或所述非空白消息槽进行非阻塞式并行入队操作;
[0077] 所述消息队列池用于缓存尚未处理的已入队消息;
[0078] 所述排队顺序管理器用于根据预设调度策略从所述消息队列池中选择需处理的指定消息,对所述指定消息进行协同的出队操作;
[0079] 所述入口映射表,根据所述目标算子ID查找所述入口映射表,获得与所述目标算子ID对应的函数入口地址;根据所述函数入口地址以及所述指定消息的指定消息槽地址,调用对应的算子执行函数,从而处理出队的所述指定消息;
[0080] 所述系统堆栈为所述协同并发式总线中所有算子共享的堆栈空间;各个算子所共享的系统堆栈空间相互覆盖,为重叠式,即非层叠式;
[0081] 并且,所述协同并发式总线内的算子仅具有就绪状态,即使当所述协同并发式总线内不存在任何消息时,所述协同并发式总线内的算子仍处于就绪状态;一旦当所述协同并发式总线内到达消息时,且当该消息所对应的算子被调度时,被调度到的算子立即获得处理器。
[0082] 优选的,所述消息为定长消息或变长消息。
[0083] 优选的,当所述并行环形分配器在所述线性内存块的最末端划割空白消息槽时,如果所述线性内存块最未端剩余的空闲空间小于所述消息占用空间值,则直接舍弃所述最未端剩余的空闲空间,所述最未端剩余的空闲空间形成废弃槽。
[0084] 优选的,所述消息填充模块首先将所述消息及所述附加管理消息填充到所述并行环形分配器分配的所述空白消息槽,得到非空白消息槽;然后所述并行入队器对所述非空白消息槽进行非阻塞式并行入队操作具体为:
[0085] 所述并行环形分配器配置有第一头指针和第一尾指针,当需要分配新的空白消息槽时,直接在当前位置的第一尾指针后面划出与所述消息占用空间值相同的空间,得到所述新的空白消息槽,然后再将所述第一尾指针非阻塞式并行移动到所述新的空白消息槽的尾部;
[0086] 所述并行入队器配置有第二头指针和第二尾指针;通过非阻塞式并行移动所述第二尾指针实现对所述非空白消息槽进行非阻塞式并行入队操作;
[0087] 其中,所述并行环形分配器配置的第一头指针和第一尾指针不同于所述并行入队器配置的第二头指针和第二尾指针。
[0088] 优选的,所述并行入队器首先对所述空白消息槽进行非阻塞式并行入队操作,然后所述消息填充模块再向入队的所述空白消息槽填充所述消息及所述附加管理消息具体为:
[0089] 所述并行环形分配器与所述并行入队器共用相同的头指针和尾指针,当所述并行环形分配器从所述线性内存块中分配出空白消息槽的同时,该空白消息槽也被所述并行入队器执行了入队操作;然后所述消息填充模块再向入队的所述空白消息槽填充所述消息及所述附加管理消息。
[0090] 优选的,在抢先环境下,在所述并行环形分配器从所述线性内存块中分配出空白消息槽之前,预先使所述空白消息槽处于休眠状态,其中,处于休眠状态的空白消息槽称为休眠消息槽;然后所述消息填充模块向所述休眠消息槽中填充所述消息及所述附加管理消息,当填充完成之后,所述休眠消息槽被激活时,即转变为活跃状态,其中,处于活跃状态的消息槽称为活跃消息槽;其中,休眠消息槽为不会被所述协同并发式总线调度给算子执行的消息槽;活跃消息槽为属于所述协同并发式总线正常调度范围的消息槽。
[0091] 优选的,采用变长消息时,通过消息槽中写入的消息长度参数是否为0区分所述休眠消息槽和活跃消息槽;当所述消息槽中写入的消息长度参数为0时,该消息槽为所述休眠消息槽;当所述消息槽中写入的消息长度参数不为0时,该消息槽为所述活跃消息槽。
[0092] 优选的,还包括:监控管理中心;所述监控管理中心用于对所述协同并发式总线内部的消息,进行集中监视、分析、控制、过滤和管理。
[0093] 优选的,还包括:空间回收模块;所述空间回收模块用于回收所述协同并发式总线内的出队后的消息本身以及所述消息槽。
[0094] 优选的,还包括:节电装置;所述节电装置用于:当所述协同并发式总线内不存在消息时,立即通知使用本协同并发式总线的应用系统进行节能调度。
[0095] 本发明还提供一种基于上述独立主动构件组装模型的可运行主动构件组装模型,所述集合P中还包括第0层主动构件;所述第1层主动构件基于消息总线进行构件组装,得到所述第0层主动构件。
[0096] 优选的,所述第0层主动构件包括:所述消息总线、第0层接口算子ID映射表、第0层别名链接表以及一个以上的第0层算子;所述第1层主动构件包括第1层虚拟消息总线、第1层接口算子ID映射表、第1层别名链接表以及一个以上的第1层算子;
[0097] 所述第1层主动构件基于所述消息总线进行构件组装,得到所述第0层主动构件具体为:
[0098] 在进行构件组装时,将所述第1层虚拟消息总线进行总线融合,得到所述消息总线;将所述第1层接口算子ID映射表进行表格融合,得到第0层接口算子ID映射表;将所述第1层别名链接表进行表格融合,得到第0层别名链接表;将所述第1层算子进行融合,得到第0层算子。
[0099] 本发明还提供一种对上述的可运行主动构件组装模型进行构件拆分方法,包括以下步骤:
[0100] 预先设定构件拆分规则,当所述可运行主动构件组装模型满足所述构件拆分规则时,按所述构件拆分规则拆分所述可运行主动构件组装模型。
[0101] 优选的,所述构件拆分规则为:当所述消息总线的调度程序由两个以上内核或处理器执行时,将所述消息总线分裂为与所述内核数量或所述处理器数量相同的分布式的对等的子总线;所述可运行主动构件组装模型中各层各个所述主动构件分别挂接到对应的所述子总线上;或者
[0102] 所述构件拆分规则为:动态统计所述可运行主动构件组装模型中各个主动构件的负荷,根据预设的负载均衡原理,动态地将所述消息总线分裂为分布式的对等的多个子总线;所述可运行主动构件组装模型中各层各个所述主动构件或算子分别挂接到对应的所述子总线上;或者
[0103] 所述构件拆分规则为:动态统计所述可运行主动构件组装模型中各个主动构的能效比,根据预设的节能原理,动态地将所述消息总线分裂为分布式的对等的多个子总线;所述可运行主动构件组装模型中各层各个所述主动构件或算子分别挂接到对应的所述子总线上;或者
[0104] 所述构件拆分规则为:动态统计所述可运行主动构件组装模型中各个主动构件的失效率,根据预设的可靠性原理,动态地将所述消息总线分裂为分布式的对等的多个子总线;所述可运行主动构件组装模型中各层各个所述主动构件或算子分别挂接到对应的所述子总线上。
[0105] 本发明的有益效果如下:
[0106] 本发明提供的独立主动构件和可运行主动构件组装模型及构件拆分方法,将多个小主动构件进行构件组装,最终得到了与各个小主动构件的构件协议相同的大主动构件。大主动构件完全消除了对下级小主动构件的调用依赖性,使得构件之间仅具有数据上的松散联系。能脱离具体应用环境,完成独立的构件功能。使得构件能够简洁、高效率地复用、重构、组合,使得整个构件系统具备高度复用性。
附图说明
[0107] 图1为现有技术提供的TinyOS 2.x基本任务调度器的结构示意图;
[0108] 图2为现有技术提供的拉模式下函数调用等效模型示意图;
[0109] 图3为本发明提供的一种构件组装实例示意图;
[0110] 图4为本发明提供的协同并发式消息总线的通用模型示意图;
[0111] 图5为本发明提供的协同并发式消息总线的一种具体应用模型示意图。

具体实施方式

[0112] 以下结合附图对本发明进行详细说明:
[0113] 实施例一:独立主动构件组装模型
[0114] 如图3所示,本发明提供一种独立主动构件组装模型,所述独立主动构件组装模型为集合P={第1层主动构件、第2层主动构件子集合...第n层主动构件子集合},其中,n≥2;所述第n层主动构件子集合中的各主动构件基于第n层虚拟消息总线进行构件组装,得到第n-1层主动构件子集合中的单个主动构件;所述第n-1层主动构件子集合中的各主动构件基于第n-1层虚拟消息总线进行构件组装,得到第n-2层主动构件子集合中的单个主动构件;以此类推,直到所述第2层主动构件子集合中的各主动构件基于第2层虚拟消息总线进行构件组装,得到第1层主动构件;
[0115] 其中,所述集合P中的各层各个所述主动构件符合相同的协议。本发明中,将多个小主动构件进行构件组装,最终得到了与各个小主动构件的构件协议相同的大主动构件。大主动构件完全消除了对下级小主动构件的调用依赖性,使得构件之间仅具有数据上的松散联系。能脱离具体应用环境,完成独立的构件功能。使得构件能够简洁、高效率地复用、重构、组合,使得整个构件系统具备高度复用性。
[0116] 其中,集合P中第1层主动构件到第n层主动构件子集合中的各个主动构件分别包括:所述虚拟消息总线、所述接口算子ID映射表、所述别名链接表以及一个以上的算子;其中,所述接口算子ID映射表用于存储接口算子ID与入口函数的对应关系;所述别名链接表用于存储引用算子ID与所述接口算子ID的对应关系;其中,所述接口算子ID为所述主动构件自身的算子标识;所述引用算子ID为挂接在消息总线上的主动构件内部的算子标识。
[0117] 下面具体说明引用算子ID、别名链接表和接口算子ID映射表:
[0118] (1)引用算子ID:
[0119] 当构件单独以源码或中间库的形式存在时,该构件内部所引用到的引用算子ID,仅是待连接确认的符号名,在多个相关的构件与配置文件一起编译连接之后,那些引用算子ID就分配为正式的ID值或变量。
[0120] (2)别名链接表
[0121] 别名链接表用于存储引用算子ID与所述接口算子ID的对应关系。优选的,别名链接表存储的所述引用算子ID与所述接口算子ID的对应关系为等值映射关系。别名链接表,操作上就是告知编译器,某构件内所引用到的其它引用算子ID,应该与哪些构件的接口算子ID链接在一起。本质上就是,确定并勾画构件与构件之间应有的数据通讯连接,以完成系统的预定功能。
[0122] 别名链接时,仅把引用算子ID与预定的接口算子ID绑定在一起,不关心算子的入口函数及其参数与消息格式。二个入口函数的参数与消息的具体规格与形式是否匹配,由应用系统自行判定与决策,从而给构件链接操作以最大的自由度。一般可以在构件静态编译连接时,由编译器进行检查;也可以在系统动态运行时,由算子自行检查确认。
[0123] 别名链接的具体实现非常简单,仅仅是把引用ID变量与已知ID变量绑定为同一个数值或变量,可以用编程语言里的别名操作或者赋值操作完成。举例说明,refId为引用算子ID,calcId为已知的接口算子ID。用C++语言实现为:aID_t&refId=calcId;用C语言实现为:aID_t refId=calcId。
[0124] (3)接口算子ID映射表
[0125] 接口算子ID映射表用于存储接口算子ID与入口函数的对应关系。
[0126] 构件内的消息入口函数可以与接口算子ID分离。也即,构件的功能实现代码部分,可以不包含接口算子ID的名称,仅包含入口函数的代码。二者的绑定映射,可以滞后一步,在构件或系统组装时,与别名链接一起完成。多个接口算子ID,可以映射指向为同一个入口函数。这在实现静态引用多实例对象时,极具价值。
[0127] 其中,虚拟消息总线是一个逻辑上、概念上的总线,不用实际去关心编码,不是一个单独明确出现的总线实体。构件总是插接到某根总线上,通过调用总线API函数,构件以硬编码的形式要求挂接到总线上。但构件单独以源码、或中间库的形式存在时,该构件并没有与某根总线实际连接在一起,并没有把总线的代码包含在构件内。只有当完成整个总线节点、或整个系统的编译连接之后,构件才与某根总线的代码连接在一起,成为总线的一个挂接部件,当独立主动构件组装模型挂接到总线上时,成为可运行主动构件组装模型,这将在实施例二中介绍。构件假设自己是在一根总线上在操作,但这根总线暂时还不存在,因此称之为虚拟消息总线。它不在构件内部存在,不影响构件的独立性。
[0128] 所述第n层主动构件子集合中的各主动构件基于第n层虚拟消息总线进行构件组装,得到第n-1层主动构件子集合中的单个主动构件,其中,n≥3具体为:
[0129] 所述第n层主动构件子集合中的各主动构件分别包括第n层虚拟消息总线、第n层接口算子ID映射表、第n层别名链接表以及一个以上的第n层算子;进行构件组装后得到的第n-1层主动构件子集合中的单个主动构件包括第n-1层虚拟消息总线、第n-1层接口算子ID映射表、第n-1层别名链接表以及一个以上的第n-1层算子;
[0130] 在进行构件组装时,将各个所述第n层虚拟消息总线进行总线融合,得到第n-1层虚拟消息总线;将各个所述第n层接口算子ID映射表进行表格融合,得到第n-1层接口算子ID映射表;将各个所述第n层别名链接表进行表格融合,得到第n-1层别名链接表;将各个所述第n层算子进行融合,得到第n-1层算子。
[0131] 所述第2层主动构件子集合中的各主动构件基于第2层虚拟消息总线进行构件组装,得到第1层主动构件具体为:
[0132] 所述第2层主动构件子集合中的各主动构件分别包括第2层虚拟消息总线、第2层接口算子ID映射表、第2层别名链接表以及一个以上的第2层算子;所述第1层主动构件包括第1层虚拟消息总线、第1层接口算子ID映射表、第1层别名链接表以及一个以上的第1层算子;
[0133] 在进行构件组装时,将各个所述第2层虚拟消息总线进行总线融合,得到第1层虚拟消息总线;将各个所述第2层接口算子ID映射表进行表格融合,得到第1层接口算子ID映射表;将各个所述第2层别名链接表进行表格融合,得到第1层别名链接表;将各个所述第2层算子进行融合,得到第1层算子。
[0134] 具体的,构件组装时,虚拟消息总线只是一个逻辑概念,不用实际去关心编码。因此,实际只需要完成接口算子ID映射表与别名链接表即可,这二者可以放在同一个配置文件里。因此,构件组装操作,就简化对应于完成一个简洁的配置文件。而实际的算子函数代码,则可存放于一个算子函数库里。该库的算子函数之间,没有任何的相互调用关系,仅仅是简单的罗列关系,大家并行存在于同一个库而已。
[0135] 配置文件里的内容,只是简单的罗列而已:接口算子ID与入口函数的对应关、引用算子ID与接口算子的对应关系。构件的引用、拆分、修改、重利用等等,也都仅仅是改变其中的对应关系而已,非常简单明了。当需要完全包含另外一个构件,使它成为自己的一个部分时,只要简单地把该构件的配置文件包含进来即可,不需更改它的函数代码部分。
[0136] 并发算子作为最基本的基础构件,可以组装构成更大、更高级的构件。在组成更大的构件之后,作为基础的算子之间,仍然没有直接的函数调用关系,仅有数据通讯关系,仍保持相互之间通过总线进行消息沟通的特点。通过一张局部的别名链接表,确定构件内部的各算子之间的数据连接与通讯关系。由于本消息总线的消息调度效率,接近或与汇编级别的顺序call调用相同,因此,大量存在的算子极少或不会降低系统的运行效率。
[0137] 如图3所示,为本发明提供的构件组装实例示意图,从图中可以看出,构件3、构件4需要组成一个大的构件Ca,构件Ca即为本发明实施例一所提供的独立主动构件;然后构件Ca与构件1、构件2需要组成更大的构件Cb,构件Cb即为本发明实施例二所提供的可运行主动构件;。构件1、构件2、构件3、构件4之间的数据传送关系,如图中左半部分所示;
实际组成的构件装配运行结构,如图中右半部分所示。
[0138] 构件1、构件2、构件3、构件4实际的函数代码,并行存放于另外的一个算子函数库中,不用关心。构件Ca的配置文件内容包含:算子ID3a、ID3b与构件3内的入口函数的对应关系,算子ID4与构件4内的入口函数的对应关系;构件3引用ID4、构件4引用ID3b的对应关系;对外公布的算子ID3a、构件4引用的算子。构件Cb的配置内容类似,不再赘述。
[0139] 以上,描述了独立主动构件组装模型的通用模型与具体实施案例。
[0140] 另外,本发明所提供的独立主动构件组装模型,内置有总线接口,用于挂接到总线上,从而使独立主动构件转化为可运行主动构件。本发明还提供一种总线接口的特例,即:协同并发式总线接口,该协同并发式总线接口用于挂接到协同并发式总线上。下面对本发明提供的与协同并发式总线接口适配的协同并发式总线进行详细介绍:
[0141] 如图4所示,本发明提供一种与协同并发式总线接口适配的协同并发式消息总线,本消息总线的并发通用模型是:并行入队、协同出队,即多入单出模型。消息在进入消息队列池之前,都属于非阻塞式并行操作;进入消息队列池之后,属于协同式串行操作。具体包括:信息提取模块、并行环形分配器、线性内存块、消息填充模块、并行入队器、消息队列池、排队顺序管理器、入口映射表和系统堆栈。以下对上述各部件详细说明:
[0142] (一)信息获取模块
[0143] 信息获取模块用于从接收到的待处理的外部并行的消息中获取目标算子ID以及消息长度值;其中,所述目标算子ID为处理所述消息的算子标识。同时用于获取附加管理消息的附加管理消息长度值,然后计算所述附加管理消息长度值与获取到的所述消息长度值的和,得到消息占用空间值;其中,所述附加管理消息长度值≥0。
[0144] 需要说明的是,本发明中采用的算子一词为英文计算机术语Actor的意译,一般翻译为“角色”。个人觉得借用数学里的“算子”这一概念,能更精确地表征Actor的含义。因此在本文中,均采用“算子”这一术语作为英文Actor的中文译词。
[0145] 从调度效率看,算子是一个比任务、进程、线程更为轻量级的并发实体,比回调函数更重量级一些。相当于纤程、协程,比纤程、协程略微轻量级一点。本发明中,消息总线内的算子仅具有就绪状态,即使当所述消息总线内不存在任何消息时,所述消息总线内的算子仍处于就绪状态;一旦当所述消息总线内到达消息时,且当该消息所对应的算子被调度时,被调度到的算子立即获得处理器。
[0146] 其中,目标算子ID可以简单地按顺序分发排列,也可以隐含一些其它意义,如:优先级、固定服务号、分布式ID号......等。例如:可以简单地将目标算子ID分为两部分:外部总线节点号和消息总线内的算子号。通过该种结构,只需简单替换掉引用的某目标算子ID,就能轻松放弃引用本地算子、转而引用存在于另外一个外部节点上的算子,实现透明的分布式计算与转移。更复杂的划分方法,甚至可以借用类似于Internet网的IP地址划分概念,实现更复杂的分布式应用逻辑。
[0147] 在实用的消息总线中,消息中的目标算子ID,一般会隐藏有其它有用的信息(如外部节点号)。因此,需要把正确的本地目标算子ID明确地转换提取出来。消息内部包含的其它若干参数,也有可能需要进行统一的格式匹配与转换。因此,需要进行参数提取与格式转换。正常结果是,得到一个正确的目标算子ID,以及消息(槽)的首地址。
[0148] (二)并行环形分配器
[0149] 并行环形分配器为非阻塞式并行的空间环形分配器,用于根据所述信息获取模块获取到的所述消息占用空间值,按环形划分原则连续动态的划割所述线性内存块,非阻塞式并行地得到与消息占用空间值相同的空白消息槽。
[0150] 当存在多个待入队消息时,则并行环形分配器动态的将线性内存块划分成多个消息槽(Slot),每个消息槽正好容纳一条完整的消息,当然,根据实际需求,消息槽中也可以容纳系统管理用的其它附加信息。这些消息槽被相邻连续地分配与回收。因此,从逻辑上看,线性内存块变成了环形的槽空间。当所述并行环形分配器在所述线性内存块的最末端划割空白消息槽时,如果所述线性内存块最未端剩余的空闲空间小于所述消息占用空间值,则直接舍弃所述最未端剩余的空闲空间,所述最未端剩余的空闲空间形成废弃槽,从而保证每个消息槽所使用的空间是平面、线性、不绕回的,使得算子与应用程序对槽空间的逻辑视图简洁、干净、自然。
[0151] 该并行环形分配器是一个高效、简洁的非阻塞式并行的空间环形分配器,相对于阻塞式分配器,消除了死锁、优先级倒置、中断不能加锁、临界区不能并发等问题;用免费的纯软件方法,实现无锁分配;用廉价的硬件方法,实现高效率的单条汇编指令的无等待分配。具体的,可以利用中断屏蔽、CAS/CAS2、LL/SC处理器原语......等,用纯软件方法,通过无锁(Lock-Free)算法进行分配;也可以利用硬件,直接实现同样的功能,得到无等待(Wait-Free)算法的效果,同时获得高效率分配的效果:一条汇编指令即可完成空间分配。用纯软件实现的无锁算法留待后述。
[0152] (三)线性内存块
[0153] 该线性内存块作为消息缓存区,应该足够大。现代的常规应用程序中,除了固定长度的内存分配外,常用的行为逻辑与指导准则为:将剩余的内存RAM空间全部分配作为堆栈空间。与此相对应,在使用本发明提供的消息总线的应用系统中,应该反过来首先固定应用系统的堆栈大小、然后将剩余的内存RAM空间全部分配作为消息缓存区。这是因为,大量并发的算子Actor是组成本系统的主体,因此存在大量不确定的消息,需要大量不确定的消息缓存。而与此同时,在本应用系统中,每个算子所调用的函数层次不是特别多,并且一般都只是很简单的直接调用,而所有算子的堆栈空间都是因为协同执行而相互重叠的,因此能轻松估计出所需要使用到的最大RAM堆栈空间,因此可以作为固定长度的RAM内存进行分配。
[0154] 如果消息缓存区不够大,导致应用系统在运行期间溢出,则将无法再接收新消息入队,而导致系统故障或者崩溃。则该错误的处理原则是:由该应用系统自行负责处理;或者重新扩大消息缓存区,或者修改应用系统的处理逻辑,或者直接让应用系统停机......等等。这与现代的常规应用程序对系统堆栈溢出的故障处理方案完全类似。通过采用这样的逻辑与机制,使得本消息总线卸下了一个本来就应该由用户自行担保的责任:无条件地保证应用系统不被大批量数据冲垮。从而大大简化了本消息总线的设计逻辑与代码,获得最广泛的软硬件适应性与移植性。
[0155] 为了增加消息总线的普适性,对于消息总线上传输的消息的内部结构,本发明只做出最少量的规定:消息分为定长消息和变长消息;对于定长消息的应用系统,一般用于相对特殊的应用环境,如ATM交换机等等类似场合。对于变长消息应用系统,应用最为广泛,具有最普遍的使用价值。
[0156] 对于定长消息和变长消息,均必须包含目标算子ID;另外,对于定长消息,消息长度值由具体应用系统及其消息总线自行定义,不必明确地出现在消息结构中;对于变长消息,消息长度值则必须明确地出现在消息结构中。消息长度值与目标算子ID本身的长度,与处理器字长密切相关,由具体应用系统及其消息总线自行定义,一般推荐为1、2、4、8、16等字节,但并不强行规定采用哪种长度。单条消息的总长度、其内部是否包含其它管理信息(如动态优先级)......等等,也是由具体应用系统及其消息总线自行定义。
[0157] (四)消息填充模块
[0158] 所述消息填充模块用于将所述消息及所述附加管理消息填充到所述并行环形分配器分配的所述空白消息槽,得到非空白消息槽。
[0159] 在并行环形分配器为并行的任一消息i进行空间分发、分配消息槽以后,该消息槽空间即被该消息私人占有。因此,可以对该消息槽任意处理。此时,即可进行消息填充操作。此阶段即使具有非常长的时间延迟,对系统其它部分也毫无影响。
[0160] 具体的,消息填充模块可以采用下列两种方案进行消息填充:
[0161] (一)第一种方案:先填充、后入队:
[0162] 具体的,消息填充模块首先将所述消息及所述附加管理消息填充到所述并行环形分配器分配的所述空白消息槽,得到非空白消息槽;然后所述并行入队器对所述非空白消息槽进行非阻塞式并行入队操作具体为:
[0163] 所述并行环形分配器配置有第一头指针和第一尾指针,当需要分配新的空白消息槽时,直接在当前位置的第一尾指针后面划出与所述消息占用空间值相同的空间,得到所述新的空白消息槽,然后再将所述第一尾指针非阻塞式并行移动到所述新的空白消息槽的尾部;
[0164] 所述并行入队器配置有第二头指针和第二尾指针;通过非阻塞式并行移动所述第二尾指针实现对所述非空白消息槽进行非阻塞式并行入队操作;
[0165] 其中,所述并行环形分配器配置的第一头指针和第一尾指针不同于所述并行入队器配置的第二头指针和第二尾指针。
[0166] (二)第二种方案:先入队、后填充:
[0167] 并行入队器首先对所述空白消息槽进行非阻塞式并行入队操作,然后所述消息填充模块再向入队的所述空白消息槽填充所述消息及所述附加管理消息具体为:
[0168] 所述并行环形分配器与所述并行入队器共用相同的头指针和尾指针,当所述并行环形分配器从所述线性内存块中分配出空白消息槽的同时,该空白消息槽也被所述并行入队器执行了入队操作;然后所述消息填充模块再向入队的所述空白消息槽填充所述消息及所述附加管理消息。
[0169] 另外,在抢先环境下,在所述并行环形分配器从所述线性内存块中分配出空白消息槽之前,预先使所述空白消息槽处于休眠状态,其中,处于休眠状态的空白消息槽称为休眠消息槽;然后所述消息填充模块向所述休眠消息槽中填充所述消息及所述附加管理消息,当填充完成之后,所述休眠消息槽被激活时,即转变为活跃状态,其中,处于活跃状态的消息槽称为活跃消息槽;其中,休眠消息槽为不会被所述消息总线调度给算子执行的消息槽;活跃消息槽为属于所述消息总线正常调度范围的消息槽。
[0170] 一般采用在消息槽中增加管理标志的办法区分休眠消息槽与活跃消息槽。作为一种简化方式,可以将管理标志隐藏在其它信息中,从而节省RAM空间。例如:采用变长消息时,有用的消息长度肯定不为零;因此,可以约定,通过消息槽中写入的消息长度参数是否为0区分所述休眠消息槽和活跃消息槽;当所述消息槽中写入的消息长度参数为0时,该消息槽为所述休眠消息槽;当所述消息槽中写入的消息长度参数不为0时,该消息槽为所述活跃消息槽。这样,只要把消息长度参数瞬间写入到消息槽中,即可激活该消息槽。
[0171] (五)并行入队器
[0172] 并行入队器用于对所述空白消息槽或所述非空白消息槽进行非阻塞式并行入队操作。
[0173] 具体的,并行入队器是消息并行转串行的关键部件,需要非常小心翼翼编码操作的相互抢占的并行行为,过此而后,转为非常轻松的协同的串行行为。由于本消息总线是一个多入单出模型,因此并行入队器在具体实现时,多数应用场合下,都能根据实际情况简化实现模型。
[0174] 并行入队器是一个高效、简洁的非阻塞式并行入队的部件,相对于阻塞式入队器,消除了死锁、优先级倒置、中断不能加锁、临界区不能并发等问题;用免费的纯软件方法,实现无锁入队;用廉价的硬件方法,实现高效率的单条汇编指令的无等待入队。具体的,可以利用中断屏蔽、CAS/CAS2、LL/SC处理器原语......等,用纯软件方法,实现无锁(Lock-Free)算法进行入队操作;也可以利用硬件,直接实现同样的功能,得到无等待(Wait-Free)算法的效果,同时获得高效率入队的效果:一条汇编指令即可完成入队操作。链表的非阻塞式、特别是无锁入队操作,已有很多的公开论文陈述,在此不再赘述。并行入队器的具体实现,与总线内部的消息队列池的具体结构与实现,密切相关。通常情况下,是操作单个或者多个含头尾指针的单链表,对其完成尾部并行入队操作。为降低并行操作的复杂性,也可以安排一个专门的单链表队列,仅用于并行转串行的入队操作;之后,再对该并串队列进行后续管理操作。特殊情况下,入队可以有其它特别解决方案。后文将描述一个特别的简洁模型。
[0175] (六)消息队列池
[0176] 消息队列池用于缓存尚未处理的已入队消息。
[0177] 消息队列池,是本消息总线的核心数据结构区,用于缓存所有尚未处理的已入队消息,配合过滤、管理、调度、挑选应该优先处理的消息。由于这时已经完全是协同操作,因此,能简单自然地设计各种调度管理算法。
[0178] 消息队列池的具体实现方案,与具体的应用系统密切相关。通常情况下,是一个含头尾指针的单链表,可以实现简单的调度算法,如:先进先出FIFO(FirstIn First Out)算法、简单的优先级排序算法......等。复杂情况下,比如,多种简单的调度算法同时存在于一个系统,这时需要使用多个单链表,以实现相对复杂的调度算法,如:时间优化的动态优先级算法、最早截止任务优先EDF(EarliestDeadline First)算法......等。特殊情况下,可能需要使用双链表、散列表等复杂的数据结构,以完成系统特殊的功能与要求。
[0179] 本发明中,对于消息队列池,采用零PCB,从而简化了并发模型,使得本消息总线具备最广泛的适应性。更为关键的,能够有效节省RAM空间。对于应用本消息总线实现并发的应用系统而言,由于构件组装,一次拥有成千上万的算子Actor是非常正常的事情。因此,零PCB就使得算子数量与RAM空间的占用毫无关联。无论存在多少算子,其所占用的RAM空间丝毫不变。这样,本消息总线就能很轻易地应用于各种RAM稀缺的场合,如:WSN应用系统中。
[0180] 零PCB,意味着算子不再能动态地表达其任务的多种状态,因此约定:总线内的算子,不再有等待状态,而只存在就绪状态和运行状态。即使消息总线内不存在任何消息时,消息总线内的算子也处于就绪状态。而当消息总线内到达消息时,消息总线内的算子排序后立即获得处理器,从而转变为运行状态。因此,整个应用系统是否处于等待状态,取决于消息总线内部是否存在消息。这为系统节能奠立了深刻的理论与技术支撑点。
[0181] 零PCB,意味着一般的算子可以不用RAM空间来动态地表达。但是,这不排除某些特别用途的算子或队列,可以占用很多RAM空间,也即,采用非零PCB来表达。比如:在EDF队列里,记录每个实时算子的截止时间
[0182] 因此,RAM零长度的任务控制块PCB,即零PCB,相对于RAM内存中非零长度的任务PCB,减少了调度执行时间,形成了高效、简洁、统一的并发基础模型,减少了RAM空间的占用,使得本并发基础模型能普遍适用于任何现有的计算机体系。
[0183] (七)排队顺序管理器
[0184] 排队顺序管理器用于根据预设调度策略从所述消息队列池中选择需处理的指定消息,对所述指定消息进行协同的出队操作。
[0185] 具体的,排队顺序管理器,利用消息队列池、各种调度算法等,对所有尚未处理的已入队消息进行调度管理。例如:设置消息的优先顺序,将最优先的消息置于队首,便于消息出队。其中,在选择队首时,可以很简单地从队列的头部,将消息提取标示出来。如果有多个队列,则需要先选择最优先的队列。由于消息格式一般比较复杂、不可预知,因此也可以简单地提取消息槽的地址作为消息地址。对于最简单的先进先出算法,排队顺序管理器甚至可以做到不以明确独立的形态出现,而是隐含在其它相关机构与代码中。将排队顺序管理器放置于并行入队器之后,可以避免复杂、繁琐、危险的并行抢占操作。由于此时已经完全是协同操作,因此,能简单自然地设计各种调度管理算法。
[0186] (八)入口映射表
[0187] 入口映射表,根据所述目标算子ID查找所述入口映射表,获得与所述目标算子ID对应的函数入口地址;根据所述函数入口地址以及所述指定消息的指定消息槽地址,调用对应的算子执行函数,从而处理出队的所述指定消息。
[0188] 入口映射表用于存储算子ID与函数入口地址的映射关系,根据目标算子ID查找入口映射表,可以获得与目标算子ID对应的函数入口地址,以便下一步跳到该入口处,执行该算子的函数。这实际上是一个汇编级别的间接地址跳转机制。该入口映射表,一般是一个按算子ID顺序、从小到大排列的地址表,算子ID本身一般不明确地出现在该表内部。为了压缩任务入口表的大小,充分利用空间,算子ID一般采用连续的编码方式。
[0189] 为节省RAM空间,适应RAM空间稀缺的应用系统,可以将该入口映射表存放在ROM中。该入口映射表也可以隐含附带或明确列出其它若干有用信息,如:算子的静态优先级等。由于此时是协同操作,因此,即使是在程序运行期间,也能轻易协同一致地修改该入口映射表,实现系统代码的运行期间热升级。这对于24小时*7天/周、连续运行的高可靠系统而言,有非常重大的现实价值。另外,入口映射表存储算子ID与函数入口地址的映射关系,对于采用任务入口地址的方案,能跨越计算机标示并行算子,直接支持完全透明的分布式并行计算。支持运行期间的代码热升级。
[0190] (九)系统堆栈与执行任务
[0191] 系统堆栈为所述消息总线中所有算子共享的堆栈空间;各个算子所共享的系统堆栈空间相互覆盖,为重叠式,即非层叠式。
[0192] 根据前面得到的函数入口地址、以及消息(槽)首地址,直接调用该算子的执行函数。与TinyOS 2.x相比,最大的区别是,本技术方案在执行时,携带有消息指针;因此,变成了主动消息模式,能实现推模式的信息传送机制。一个算子完全退出以后,其所占用的堆栈空间也完全清空。由于系统内的所有算子都是协同执行,因此,它们都共享相同的系统堆栈空间。也即,所有算子的堆栈空间是重叠的,相对于层叠式的任务堆栈,本发明提供的重叠的协同系统堆栈,大量减少了RAM堆栈空间的占用,使系统更具普适性;便于评估堆栈空间的最大使用量,便于RAM空间分配管理工作。在算子运行期间,消息(槽)是属于该算子完全私有的。因此,在不妨碍总线运行的情况下,算子能对该消息任意处理。如:重复或优先使用、发送、转发、更改该消息(槽),以提高系统运行效率。
[0193] (十)监控管理中心
[0194] 监控管理中心用于对所述消息总线内部的消息,进行集中监视、分析、控制、过滤和管理。比如:统计消息总线内所有算子的实际运行时间;清除发给某算子的某类消息;甚至强制终止运行某失控的算子......等等。一般主要用于系统调试与测试阶段,在系统正式运行期间可以不必存在。
[0195] (十一)空间回收模块
[0196] 空间回收模块用于回收所述消息总线内的出队后的消息本身以及所述消息槽,即:用于消息本身的废弃回收、以及消息槽空间的废弃回收。消息本身的废弃,属于并行入队器的多入单出模式中的出队操作。在很简单的应用系统中,可以在队首选择的时候统一进行,以便算子运行的时候,可以很简单地消除废弃标志,重复利用该消息。消息槽空间的回收:正常情况下,属于并行环形分配器的多入单出模式中的空间回收操作,也可由硬件实现。
[0197] (十二)节电装置
[0198] 节电装置的具体的实现方式与应用系统硬件密切相关。由于本消息总线能根据内部是否存在消息,从而即时知晓系统是否处于等待状态。因此,在总线内部不存在消息时,立即通知使用本消息总线的应用系统进行节能调度。当有消息发生时,再通知硬件恢复正常运行状态。
[0199] 在很多应用场合下(如:8051单片机),处理器没有CAS/CAS2指令、也没有LL/SC等用于并行操作的高级同步原语。因此,只能用开关中断的方法模拟实现类似原语。这会降低总线的调度效率。这时,可以对通用模型做出一些简单的适应性更改,以适应具体的应用环境,提高系统效率。举例说明:总线内部算子产生的消息多、而外部中断环境产生的消息少。这时,可以利用该特点,设置2个总线消息缓存空间。中断消息入队是竞争性的,使用开关中断实现原语。算子消息入队是协同性的,则无需使用开关中断,因此能提高调度效率。甚至能针对中断优先的特点,做出更高效率的技术修正,使得二者能共用同一个消息缓存。
[0200] 对于硬实时系统,要求某些关键操作,必须在确定内的时间界限内完成。本通用协同模型,可以在优先级调度的情况下,稍加变更予以实现。对于响应速度非常高速、严格的情形,可以直接在硬件中断处理函数内部完成。对于响应时间可以稍微推迟一步、能利用总线调度的情形,可以安排在最高协同优先级下运行算子。入队操作也安排在最高优先级,能保证入队时没有等待滞后。同时,拆分所有超过规定时间的算子。以使得在规定时间内,总线对任一算子能及时执行完毕。进而,能在规定时间内,调度到最高优先级的算子,完成硬实时响应。由于本模型有集中监控中心,很容易监测各算子的运行时间。因此,很容易定位到那些超过规定时间运行的算子,帮助完成硬实时响应的设计工作。
[0201] 本发明提供的消息总线,存在一个简洁高效的具体特例。该特例的功能不是特别齐全,但执行性能特别高效,能实现算子并发操作,满足一般的并发应用环境,或作为其它并发应用的基础。在借用硬件实现关键原子操作时,其执行效率,可以与汇编级别的子程序调用,具备相同或非常接近的性能。
[0202] 在该特例中,并行环形分配器与并行入队器合二为一。采用休眠消息槽与消息激活机制,实现简单的FIFO排序,在入队的同时,自然完成排队操作。具体工作步骤为:
[0203] S1、休眠标识、空间分配、入队。特殊硬件完成,单条汇编指令可完成。
[0204] S2、外部消息复制进入消息槽。
[0205] S3、最简单的FIFO排队。隐含在S1操作中,不消耗时间。
[0206] S4、消息队首出队。单条汇编指令可完成。参数提取,一般情况可省略。
[0207] S5、算子ID查表,跳转执行。汇编级的间接调用指令可完成。
[0208] S6、空间回收。特殊硬件完成,单条汇编指令可完成。
[0209] 对比汇编级别的子程序调用过程,S1相当于改变堆栈指针,S2相当于参数压栈,S5相当于间接CALL汇编指令,S6相当于参数退栈。S3不消耗时间。因此,仅S4是多出的执行时间,是非常简单的操作,单条汇编指令即可完成。因此,总体执行时间,仅多出1条汇编指令时间。在消息(或参数)较多时,所占时间比重非常少。因此,可以做到非常接近的执行性能。如果进一步优化操作,采用更复杂的硬件,可以做到相同的执行性能。
[0210] 下面对该特例进行详细说明:
[0211] 为叙述简单起见,先约定两个术语:让先环境、抢先环境。
[0212] 通常,在低端嵌入式应用环境中,普遍采用单核心单处理器的单片机,不采用操作系统。应用软件采用结构化、模块化、顺序编程技术,组装构成整个应用系统,直接运行在裸机状态下。外部环境事件发生时,利用中断处理程序抢先抢占主程序,捕捉外部事件,并把事件状态保存在某些事先约定好的特定位置。同时,主程序使用一个很大的死循环,轮回检查是否有外部事件发生。若有发生,则按照事先的约定,检查提取外部事件的状态,处理后输出。
[0213] 很多应用,类似于上述应用场景,主循环总是被外部中断所抢占,但不会出现主循环抢占外部中断的情况。也即,只要有外部中断代码在运行,主循环肯定暂停执行。这种软件执行环境,称之为让先执行环境,简称为“让先环境”。比如:单核单处理器时,LINUX执行实时优先调度政策,所导致的实时线程运行环境,当其最低优先级的线程充当主循环时,即构成让先环境。
[0214] 与之相反,在多核处理器、或单核多处理器、或普通时间片式抢先调度时,主线程与其它线程能相互抢占,或同时并行交叉执行。这种软件执行环境,称之为抢先执行环境,简称为“抢先环境”。
[0215] 在实现本消息总线时,主循环作为调度程序,完成消息出队、调度、协同运行算子的功能;其它外部中断,则相互抢占、把消息送入系统队列。抢先环境下,调度程序与外部中断相互抢占、交叉执行。因此,外部中断在填充消息槽、但尚未完全填充完毕时,调度程序就有可能运行。此时,调度程序就有机会接触到那条半成品式的不完整消息。因此,需要采取一定的措施,保证调度程序不会把那条半成品消息,当成是正常的消息使用。在让先环境下,外部中断填充消息槽时,调度程序没有机会被执行。调度程序要么看不见新消息,要么看见的就是一条入队后的完整消息。利用这个特点,在让先环境下,就可以简化并行入队算法,不用给消息(槽)打上休眠标志。
[0216] 本实施例可以用于抢先环境、透明分布环境,基于x86 32bit多核系统。
[0217] 本实施例最核心的技术要点在于,将并行环形分配器与并行入队器合并操作,将环形空间的头尾指针,同时当作是消息队列的头尾指针。二个队列合用同一付头尾指针。这样,消息槽刚刚从线性空间中被分配出来、进入到环形槽空间中的同时,就意味着该消息槽已经进入了系统消息队列。
[0218] 这时,在抢先环境下,为防止调度程序误用这个新消息槽(此时尚未填充消息数据),需要事先给该消息槽写上休眠标志。该休眠标志隐含在该消息槽的长度参数里。当长度为0时,代表该消息槽在休眠,尚未填充数据,调度程序应该忽略之。
[0219] 消息格式为不定长二进制数据,分为消息头、消息体二部分。消息体可以是任意数据、小于65536-8字节的任意长度。消息体为0字节也是合法的,这时,整个消息就没有消息体,只包含消息头部。消息头有三部分:2字节的消息长度参数size、2字节CAS2计数器cas2cnt、4字节算子id。共8个字节,正好在32BIT x86CPU的一次CAS2操作范围内。
[0220] 在抢先环境下,利用无锁算法,预写休眠标志需要使用到CAS2操作。为防止CAS2无锁操作时的ABA问题,cas2cnt计数器是必须的。具体原理可参看相关论文,此处不再赘述。在让先环境下,不需要使用休眠标志,也不需要使用到CAS2操作,因此cas2cnt没必要存在,可以舍弃。
[0221] 本案例中,CAS操作用x86的汇编指令cmpxchg完成,一次可操作4个字节;CAS2操作用汇编指令cmpxchg8b完成,一次可操作8个字节。在x86架构下,用汇编指令lock完成内存总线锁定,以完成多核时的CAS/CAS2操作。
[0222] 32BIT的算子ID号可以极简单地划分为2个部分:节点号、算子号。节点号为0时,随后的算子号,被看作是本总线内的算子。节点号不为0时,意味着目标算子不在本总线内,而是在其它外部节点:随后的算子号,因此被当成是该外部节点内的算子。节点号与算子号各占多少个BIT位,可以在应用系统中,事先约定。每个外部节点,需要一个本地算子代为处理一些必要的事务,如:把该消息转发到一条通向该外部节点的通信管道中去......等等。该本地算子,称为代理算子。
[0223] 环形槽空间队列有头指针head、尾指针tail,兼作系统消息队列的头、尾指针。当头、尾指针相等时,表示环形槽空间内没有消息(槽),为空队列。不考虑环形槽空间溢出的情形,此种例外故障由用户应用程序自行处理。因此,尾指针始终指向线性内存块的空闲区域。
[0224] 消息槽分配时,直接在尾指针处,按8字节边界对齐后,划出相应长度的空闲空间,然后移动尾指针:这也意味着,消息槽也同时进入了系统消息队列。在线性内存块的最末端分配时,其所剩余的空闲空间,可能无法容纳一条完整的消息,则把该末端空间分配成一个废弃的消息槽。新消息在下个空闲位置(线性空间的最开始端)连续分配。由于消息槽边界始终是8字节对齐,与消息头部的长度相等。因此,最末端的废弃消息槽,最少也能容纳下消息的头部,不至于在用CAS2操作、并发写入休眠标志时,出现超边界读写的故障。
[0225] 由于消息槽的长度刚好容纳一条消息,因此,由消息的长度能直接计算出消息槽的长度。而消息槽是连续分配的,因此,消息槽的长度实际上也隐含了下一个消息槽的位置。因此,不需要其它附加信息,所有的消息就可以组成一个FIFO的单链表。从首指针开始,可以按入队顺序,遍历到所有的队列内消息。
[0226] 消息从队列头指针处直接出队,然后,队列头指针head指向下一个消息槽:这也意味着,前消息槽空间已被废弃回收,进入了自由空闲的线性空间。消息使用完毕后,在不出队的情况下可直接废弃。废弃标志隐含在头部的算子ID中。ID为0,意味着该消息已被废弃,调度程序不再关注它。ID不为0,意味着它是有效消息,需要调度执行。
[0227] 这样,并行入队的消息,只从队列尾部入队,只修改队列的尾指针tail;而出队的消息,只从队列头部出队,只修改队列的头指针head。因此,不采用其它临界资源保护措施,也能自然轻松地完成并发竞争性的出入队操作,提升执行效率。
[0228] 参看图5,本案例最为核心的操作有三个:
[0229] A1、分配空槽入队;A2、提交激活槽;A3、调度执行。
[0230] 需要发送消息的外部环境或内部算子,根据消息长度,调用A1操作,得到休眠的私有消息槽。然后,把消息的其余部分复制到该消息槽。最后,根据消息的目标算子ID、以及消息的长度参数,调用A2操作,激活该消息。等待总线调度处理该消息。
[0231] 本案例的总线A3操作,非常简单直观。只是简单的处理一下休眠与废弃回收问题即可。其中,代理算子这个概念,放在调度程序内实现,对于透明分布计算有很大的好处。这样,就可以在构件组装的链接配置文件中,直接把构件内使用到的ID号,链接到外部节点里。而不用再另外编码生成本地算子,再通过该算子,转发消息到外部节点。
[0232] 总线A3操作时,对于普通算子,先标示废弃该消息,再执行该消息对应的目标算子。理由在于,这可以给该算子一个重复利用该消息的机会。只要该算子清除该废弃标志,就可重复使用该消息,提升系统执行效率。比如:在错误处理算子中,把消息的ID修改为另外的算子,就可以把消息快速优先地转发给后续的错误处理算子。由于该条消息此时仍处于消息队列头部,因此能获得优先执行。
[0233] 总线A2操作,在大于0的长度参数sz瞬间写入到休眠消息头部的size域时,该休眠消息槽被激活(消息槽休眠时,其头部的size域为0)。为提高执行效率,仅仅在消息队列刚刚为空时,也即,本条消息是消息队列内的第一条消息时,才发送信号,唤醒睡眠中的调度程序。唤醒信号也可以多次重复发送。
[0234] 总线A1操作是无锁标示、分配与入队操作,采用了CAS/CAS2操作。
[0235] (1)对尾指针tail及其所指向的消息槽头部做一个快照snap。这时的snap,实际上可能是无用的垃圾数据,也有可能是它人已处理好的有效头部:可能是已做好标志的头部、或者是正在填充的消息、或者干脆是已完全填好的消息头部。然后反复与tail指针实时比较,以确保所获得的快照、是从最新的队尾所获取。成功之后的snap,不再可能是正在填充或填充完毕的头部。因为,那种情况下,tail指针必然已被它人改变。
[0236] (2)向快照snap对应的内存写入相同的标志M:休眠且有效的消息,其头部size域为0,且id域不为0。有时它人已抢先填充,为防止破坏同一块内存,采用CAS2原子操作。CAS2操作时,其计数器cas2cnt域(scnt),在原来snap时获得的数值上加1,然后与标志M共同写回去。这样,该CAS2操作就保证了:在写入标志M之前、并行竞争写入时,有且仅有一次标志M的成功写入;在写入标志M之后,仅有头部的cas2cnt域能被修改。因此在整体上保证了:标志M被可靠地提前写入,且不会破坏它人后续写入的其它有用的头部信息。
[0237] (3)修改队列尾指针tail,以抢先入队。由于环形空间需要回绕一整圈以后,才可能会以极其微小的概率回到原处。因此,新、旧消息槽指针基本不可能相等,不存在ABA问题。仅采用CAS操作,就可完成竞争性的tail指针写入,完成空间分配与入队操作。
[0238] 以上即为非阻塞入队的协同并发式消息总线的一个具体实施例。
[0239] 本发明提供的非阻塞入队的协同并发式消息总线,能够有效克服现有“并发”实现技术的弱点,高效可靠地实现“并发”技术、并行编程,具有普适、廉价、高效、可靠、节能、复用、透明分布、微内核、内在支持对象技术等一系列优点。具体的,包括以下优点:
[0240] (1)普适性:能广泛应用于各种计算机体系结构中,如:单处理器系统、多向量系统、大规模并行系统、对称多处理系统、集群系统、向量机、巨型机、嵌入式系统等;也能广泛应用于各类处理器架构或各种CPU中,如:X86架构、RISC架构、ARM处理器、8051微处理器、单片机等;也能广泛应用于各类操作系统、各类软件系统中,如:IBM OS/400系统、Windows系统、Unix系统、iOS系统、vxWorks系统、ucOS II系统、顺序编程、结构化编程、模块化编程、数据库系统等。对于这些千变万化的软硬件环境,均可使用统一的并发技术模型实现。
[0241] (2)廉价性:可以利用现有的软硬件环境直接实现,与现有的软硬件系统与技术也完全相互兼容。为了获得更多优势,也可以采用非常廉价统一的硬件设施,完成技术模型中的关键原子操作。
[0242] (3)高效性:空间效率高:其核心C语言源代码不超过数百行。时间效率高:并发效率优于现有普通线程技术,可以超过一个数量级以上;如果采用硬件设施、完成关键原子操作后,与汇编级别的子程序调用指令相比,并发效率可以达到同等级别;也即,可以在数个或数十个机器指令周期内完成一次并发调度操作。开发效率高:匹配特有的编程模型与组装复用技术,与现有普通的模块化编程、对象化编程相比较,开发效率可以超过一个数量级以上。
[0243] (4)高可靠性:其核心代码非常少,非常容易检查测试正确;采用无锁或无等待技术实现并发,核心永不会死锁崩溃;采用协同并发技术,消除大量无谓的临界条件竞争,避免应用程序时序故障;采用构件复用编程模型,重复使用已证明可靠的构件组装系统。
[0244] (5)节能特性:采用消息与事件驱动机制。在没有负荷时,系统能即时自动检测,并进入节能状态。
[0245] (6)透明分布计算特征。仅由ID号代表系统内的并发算子Actor,并发算子Actor之间仅通过消息沟通,与该算子存放于何处、在何处执行毫无关联。因此,天然适应多核处理器CMP(Chip Multi-Processor)结构、对称多处理器SMP(Symmetrical Multi-Processor)结构、非对称多处理器AMP(AsymmetricalMulti-Processor)结构、非一致存储访问NUMA(Non-Uniform Memory Access)结构、海量并行处理MPP(Massive Parallel Process)结构、计算机集群、分布式计算......等等并行与分布式环境。轻松进行负载平衡、计算转移等功能,轻松提升计算效能,能在技术上实现全球统一计算环境。
[0246] (7)微内核特征:核心代码微小,并通过高效的消息总线,实现并发机制。操作系统完全可以高效率地架构在它上面,与单内核系统一争高下。
[0247] (8)支持面向对象技术:能容纳超大规模的并发算子Actor构件,所有算子均通过高效率的消息总线通讯,完美模拟与实现了对象技术中的主动对象的行为与机制。
[0248] 实施例二可运行主动构件组装模型
[0249] 本实施例与实施例一的区别在于,在实施例一的集合P中还包括第0层主动构件;实施例一的第1层主动构件基于消息总线进行构件组装,得到所述第0层主动构件。
[0250] 其中,第0层主动构件包括:所述消息总线、第0层接口算子ID映射表、第0层别名链接表以及一个以上的第0层算子;所述第1层主动构件包括第1层虚拟消息总线、第1层接口算子ID映射表、第1层别名链接表以及一个以上的第1层算子;
[0251] 所述第1层主动构件基于所述消息总线进行构件组装,得到所述第0层主动构件具体为:
[0252] 在进行构件组装时,将所述第1层虚拟消息总线进行总线融合,得到所述消息总线;将所述第1层接口算子ID映射表进行表格融合,得到第0层接口算子ID映射表;将所述第1层别名链接表进行表格融合,得到第0层别名链接表;将所述第1层算子进行融合,得到第0层算子。
[0253] 通过本实施例,将实施一得到的独立主动构件组装模型挂接到消息总线上,即得到可运行主动构件组装模型。其中,该消息总线可以为现有技术中任意一种实体总线,也可以为实施例一介绍的协同并发式消息总线,本发明对此并不限制。
[0254] 实施例三构件拆分方法
[0255] 本实施例提供一种对可运行主动构件组装模型进行构件拆分方法,包括以下步骤:
[0256] 预先设定构件拆分规则,当所述可运行主动构件组装模型满足所述构件拆分规则时,按所述构件拆分规则拆分所述可运行主动构件组装模型。
[0257] 本发明提供下列四种构件拆分规则:
[0258] (1)第一种构件拆分规则
[0259] 构件拆分规则为:当所述消息总线的调度程序由两个以上内核或处理器执行时,将所述消息总线分裂为与所述内核数量或所述处理器数量相同的分布式的对等的子总线;所述主动构件组装模型中各层各个所述主动构件分别挂接到对应的所述子总线上。
[0260] 具体的,由于总线是协同调度与执行的,因此,一根总线只适合于由一个处理器的一个内核执行总线的调度程序,不能由多核或多处理器同时执行同一根总线的调度程序。在多核或多处理器系统中,如果一根总线的消息负荷非常大,仅由一个处理器的一个内核执行该总线的调度程序,显得力不从心。那么,可以根据内核与处理器的数量,把该总线分裂成2根甚至多根子总线,每个处理器内核负责运行一根子总线。这样,就能完成负荷的自动转移工作。由于算子之间都是消息通讯,某个算子具体在哪根子总线上运行,并不影响原来单根系统总线上算子的数据通讯关系。由于信息的局部性原理,构件内部的算子之间的通讯,相对于构件外部的通讯,一般应该频繁很多。因此,总线分裂的原则,应该以构件为单位进行划分。这样,构件内部原来不存在的虚拟消息总线,现在又重新实体化为实际的子总线。当然,如果需要总线分裂,那么原来在编译链接时,很多可以舍弃的构件信息,就需要保持记录,以保证能够重建与复现原来的构件结构与信息。
[0261] (2)第二种构件拆分规则
[0262] 所述构件拆分规则为:动态统计所述主动构件组装模型中各个主动构件的负荷,根据预设的负载均衡原理,动态地将所述消息总线分裂为分布式的对等的多个子总线;所述主动构件组装模型中各层各个所述主动构件或算子分别挂接到对应的所述子总线上。
[0263] (3)第三种构件拆分规则
[0264] 所述构件拆分规则为:动态统计所述主动构件组装模型中各个主动构件的能效比,根据预设的节能原理,动态地将所述消息总线分裂为分布式的对等的多个子总线;所述主动构件组装模型中各层各个所述主动构件或算子分别挂接到对应的所述子总线上。
[0265] (4)第四种构件拆分规则
[0266] 所述构件拆分规则为:动态统计所述主动构件组装模型中各个主动构件的失效率,根据预设的可靠性原理,动态地将所述消息总线分裂为分布式的对等的多个子总线;所述主动构件组装模型中各层各个所述主动构件或算子分别挂接到对应的所述子总线上。
[0267] 本发明提供的独立主动构件和可运行主动构件组装模型及构件拆分方法,将多个小主动构件进行构件组装,最终得到了与各个小主动构件的构件协议相同的大主动构件。大主动构件完全消除了对下级小主动构件的调用依赖性,使得构件之间仅具有数据上的松散联系。能脱离具体应用环境,完成独立的构件功能。使得构件能够简洁、高效率地复用、重构、组合,使得整个构件系统具备高度复用性。
[0268] 以上所述仅是本发明的优选实施方式,应当指出,对于本技术领域的普通技术人员来说,在不脱离本发明原理的前提下,还可以做出若干改进和润饰,这些改进和润饰也应视本发明的保护范围。
高效检索全球专利

专利汇是专利免费检索,专利查询,专利分析-国家发明专利查询检索分析平台,是提供专利分析,专利查询,专利检索等数据服务功能的知识产权数据服务商。

我们的产品包含105个国家的1.26亿组数据,免费查、免费专利分析。

申请试用

分析报告

专利汇分析报告产品可以对行业情报数据进行梳理分析,涉及维度包括行业专利基本状况分析、地域分析、技术分析、发明人分析、申请人分析、专利权人分析、失效分析、核心专利分析、法律分析、研发重点分析、企业专利处境分析、技术处境分析、专利寿命分析、企业定位分析、引证分析等超过60个分析角度,系统通过AI智能系统对图表进行解读,只需1分钟,一键生成行业专利分析报告。

申请试用

QQ群二维码
意见反馈