一种实现快速数据传递的方法 本发明涉及在多任务系统中,尤其是在高效率的实时系统中,实现快速数据传递的方法。
对于高效的实时多任务系统,尤其是在有大量任务间数据传递的软件系统,如通讯系统中,数据传递效率的高低,将直接影响到系统的性能,并往往成为决定系统开发成败的关键性因素。
在多任务系统中,任务间数据传递的最常用的工具是队列,在现有技术的大多数情况下,操作系统都提供用于数据传递的队列。在进行数据传递时,一般采取两种方法:
方法一
发送任务将数据块拷贝到队列中,然后通知数据接收任务从队列中将数据拷贝到自己的数据区中。使用这种方法,由于数据拷贝的次数较多,不可避免带来效率低下的缺点。同时,当传递的数据块大小不确定时,队列的每个节点占用内存的大小也不好确定,实现这样的队列往往也将影响程序运行的效率。
方法二
发送任务动态申请一块内存,然后将数据拷入这块内存中。发送任务将内存的指针放入队列,此后由接收任务在适当的时候从队列中将指针取出,通过该指针去获取所需的数据。使用此种方法,数据拷贝的次数比方法一要少,但是动态内存的申请和次数增加。由于动态内存的管理和队列的实现较复杂,并且动态内存地方式和队列的实现相对孤立,不能利用两者的一致性提高数据传递的效率,因而还是往往不能满足快速数据传递的要求。
为了克服上述方法的缺点,本发明提出了一种可用于实现任务间快速数据传递的方法,以实现在软件系统中,尤其是在有大量消息传递的通信系统中的快速数据传递,达到提高通信效率,增强系统对数据传递处理能力的目的。
本发明所提出的快速数据传递方法是一种综合的数据传递策略,它是在提出了三种快速数据传递的子方法的基础上,根据实际情况合理地对方法加以选择,从而达到最大限度地提高数据传递效率的目的。
一种以链表形式进行数据传递的方法,其特征在于,包括以下步骤:以内存块大小为分组依据,建立数个内存块组,同一内存块组中,使其若干具有相同大小的内存块,并初始化;利用链表变量确定一个环形双向链表,并对其进行初始化操作;数据发送任务申请动态内存块;将数据写入动态内存块;将动态内存块放入数据传递链表;通知数据接收任务;数据接收任务获得通知后获取内存块;数据接收任务使用完内存块后将其释放。
一种以数组形式进行数据传递的方法,其特征在于,包括以下步骤:确定一个给定大小的数组,并分别以HeadIndex、TailIndex表示头、尾索引号;判断数组中数据存放是否已超过数组容量的上限,如果已超过数组容量的上限,则认为是“错误处理”;否则,发送任务将数据放入相应的数组元素中,将尾索引指向数组下一元素,通知数据接收任务;判断接收任务是否有可接收数据,如不是,则结束;如是,则数据接收任务从数据传递数组中获取头索引所对应的数据;将头索引指向数据传递数组的下一个元素。
一种采用接收来自发送任务的最新数据进行缓存的数据传递的方法,其特征在于,包括以下步骤:首先申请两块数据区,分别标识为数据区0和数据区1,并初始化;初始发送和接收索引号;发送索引号是否为0?如是,则发送索引号设为1,如不是,则发送索引号设为0:发送任务将数据写入发送索引号对应的数据区;接收任务将发送索引号的值赋给接收索引号;接收任务将发送索引号设为“0”和“1”之外的值;接收任务通过访问接收索引号所对应的数据区获得所需最新数据。一种实现快速数据传递的方法,其特征在于,包括以下步骤:根据所传递数据的特点,作如下的判断,进行相应的处理;当数据传递量较大,且无法对数据传递量作适当限制时,采用链表法来进行任务间的数据传递;当数据传递量可以确定一个上限时,且满足在任一时刻,发送任务已经发出而未被接收任务获取的数据量小于所确定的上限,使用数组法来完成数据的传递;当数据接收任务只需要使用来自发送任务的最新数据时,采用缓存法。
通过对本发明的附图和详细说明的了解,将有助于理解本发明所描述的快速数据传递方法的特性和优点。
图1是用于动态内存管理和数据传递的双向环形链表的示意图。
图2是链表法的实现过程的流程图。
图3是数组法的实现过程的流程图。
图4是缓存法的实现过程的流程图。
本发明所提出数据传递方法实际上包含了三个子方法,分别为链表法、数组法和缓存法。采用如背景技术中所述的常用数据传递方法中第二种方法的思路,再克服其动态内存的管理和队列的实现方式复杂,以及动态内存的管理和队列的实现相对孤立的缺点,使用双向链表来统一进行动态内存管理和任务间的数据传递,从而形成了本发明中的第一种任务间快速数据传递的方法,即链表法。此方法对数据传递的特点没有限制,是一种可通用的高速数据传递方法。
本发明中的第二种子方法是利用数组来传递任务间的数据,此方法效率要高于链表法,但是传送数据的流量要受数组大小的限制。
本发明中的第三种子方法称之为缓存法,是几种方法中效率最高的一种,但是只适用于特定的数据传送。当数据接收方只需要获取来自数据发送任务的最新一组数据时可以使用此方法。缓存法利用两块内存来进行数据传递,其中一块内存用于存放接收任务正在使用的数据,另一块提供给发送任务,用于存放最新的发送数据。
本发明中的快速数据传递方法是三种子方法按照如下原则的组合:
1.当数据传递量较大,且无法对数据传递量作适当限制时,可使用链表法
来进行任务间的数据传递。
2.当数据传递量可以确定一个上限时,可使用数组法来完成数据的传递。
此时要求在任一时刻,发送任务已经发出而未被接收任务获取的数据量
必须小于一个给定的上限。
3.当数据接收任务只使用来自发送任务的最新数据时,可以采用缓存法。
使用该方法时,过时的数据将自动被覆盖掉。
在一个系统中,任务间数据传递的方式可以根据上述原则,按照实际情况选用上述三种方法的某一种或某几种方法的组合,这就是本发明所提出快速数据传递方法的第一步。其后,就可以根据所选用的子方法,具体进行各自不同的数据传递的后续步骤。
结合图1和图2,将描述链表法的实现方式。
在图1中,链表变量10用于标识环形双向链表,当链表用于实现队列的功能时,链表变量10可作为队列的入口和出口。内存块11和12分别代表链表上的一个节点,用于存放用户数据。在整个链表中有两类节点,即链表变量节点和内存块节点。每个链表除了一个链表变量节点外,其余的都是内存块节点。链表上的每个节点都带有两个指针成员变量NextPtr和PrevPtr,分别指向该节点的上一个节点和下一个节点的地址。链表变量节点10除了NextPtr和PrevPtr成员变量外,还包含了一些用于链表控制的成员变量。内存块节点除了NextPtr和PrevPtr成员变量外,还包含了一些内存控制变量和用户数据区。当链表用作队列时,链表变量节点10将作为队列的尾部,链表变量节点10的前一个节点作为队列的头部。当从链表中获取节点时,将链表变量节点10后的第一个节点取出;当往链表中添加节点时,将新增的节点放置在链表变量节点10之前。
参考图2,在运行初期,首先获取一块足够大的内存,再将其分割成几组内存块,同一内存块组中的内存块具有相同的大小,内存块的结构与图1中的内存块11和12相同,都具有NextPtr和PrevPtr成员变量。利用NextPtr和PrevPtr成员变量将内存块组中的各内存块放入一个环形双向链表中去,相同大小的内存块不同的内存块组对应不同的双向链表,同一链表中的内存块都具有相同的大小。这样,所有的动态内存块就成了几个环形双向链表的集合。(步骤201)
为了进行数据传递,用户需要利用链表变量来构造一个环形双向链表,并对其进行初始化操作。(步骤202)
当数据发送任务需要进行数据传递时,首先需要申请动态内存。在申请动态内存时,根据申请的内存块的大小,在尺寸大于申请的内存块的大小的动态内存块环形双向链表中,选择一个内存块尺寸最小的内存块链表,并从其中取出一个内存块节点作为分配出的动态内存。(步骤203)
数据发送任务获得动态内存之后,将数据放入动态内存块的用户数据区中(步骤204),然后利用内存块的NextPtr和PrevPtr成员变量,将内存块放入步骤202中定义的数据传递链表中去。(步骤205)
数据发送任务通知数据接收任务接收数据。(步骤206)
数据接收任务从数据传递链表中取出动态内存块,通过访问该内存块的用户数据区即可获得所需的数据。(步骤207)
数据接收任务在使用完所接收到的动态内存块后,应当将其释放。释放动态内存块的操作就是利用动态内存块的NextPtr和PrevPtr成员变量将该内存块重新放入与其大小对应的动态内存块链表中去。(步骤208)
从上述说明中可以看出,数据传递过程中的动态内存申请和队列操作,实际上只是对内存块的NextPtr和PrevPtr成员变量进行操作,过程简单而高效,大大提高了数据传递的速度;同时由于内存管理和数据传递使用了同样的链表,因而可以将两个独立的过程统一成一个高效的过程,从而使得链表法的数据传递具有较高的效率。由于环形双向链表中可存放的数据量的大小是没有限制的,因此链表法可以实现任意流量的数据传递。
图3描述了数组法的实现步骤。为了进行数据的传输,首先确定一个给定大小的数组(步骤301)。数组的大小决定于最大传输数据量的大小。然后定义两个索引HeadIndex和TailIndex,分别用于表示存放第一个和最后一个有效数据的数组元素的下标。在使用该数组之前,需要将HeadIndex和TailIndex初始化为“0”值(步骤301)。
在需要进行数据传递时,发送任务首先判断数组中存放的数据量是否已经达到数组能够存放数据数量的上限。(步骤302)。如果是,则进行相应的错误处理(步骤303)。
当判断出数组中还存在可以存放数据的空闲元素后,发送任务将数据放入TailIndex所对应的数组元素中(步骤304),然后TailIndex将指向下一个数组元素。当TailIndex等于数组的大小时,TailIndex将被赋为“0”,从而重新指向数组的起始元素,实现对数组的循环操作。(步骤304)。
数据发送任务通知数据接收任务接收数据。(步骤305)
数据接收任务获得通知信息后,首先判断数组中是否有有用数据,如果有,则将HeadIndex所对应的数组元素取出,即可获得数据发送任务发出的数据。数据接收任务取出HeadIndex所对应的数组元素后,HeadIndex将指向下一个数组元素。当HeadIndex等于数组的大小时,HeadIndex将被赋为“0”,以实现对数组的循环操作。
由于数组法在进行任务间的数据传递时,只使用了简单的数组操作,即可实现比链表法更高效的数据传递。
当接收任务只需要接收来自发送任务的最新数据时,缓存法就成了最高效的数据传递方式。如图4所示,首先申请两块数据区,分别标识为数据区0和数据区1。(步骤401)
定义两个索引号SendIndex和ReceiveIndex。当SendIndex为“0”时,表示数据发送任务已将数据放入到数据区0,当SendIndex为“1”时,已将数据放入到数据区1,当SendIndex为其它值时,表示数据发送任务未发送任何数据。SendIndex应当被初始化为“0”和“1”以外的值;ReceiveIndex用于标识数据接收任务正在使用的数据区,ReceiveIndex为“0”表示数据接收任务正在从数据区0提取数据,为“1”时表示数据接收任务正在从数据区1提取数据。(步骤402)
发送数据时,发送任务置SendIndex为“0”和“1”之中之一且不同于ReceiveIndex的值,即当ReceiveIndex为“0”时,SendIndex取为“1”;当ReceiveIndex为“1”时,SendIndex取为“0”。(步骤403、404、405)
发送任务将数据写入SendIndex所对应的数据区(步骤406);
接收任务在适当的时候将SendIndex的值赋给ReceiveIndex(步骤407),并将SendIndex置为除“0”和“1”以外的值(步骤408)。然后通过访问ReceiveIndex所对应的数据区,接收任务即可获得来自发送任务的最新数据。(步骤409)
缓存法利用对SendIndex和ReceiveIndex的操作,即可实现任务间的数据传递。使用该方式进行数据传递,无需动态内存的申请和释放,因此是效率最高的。
如上所述,综合使用本发明所述的三种方法,可以在多任务的软件系统中实现任务间高效的数据传递,这在各种对效率要求较高的实时系统中,尤其是在与通信有关的系统中大有用武之地。