一种实现通信过程零拷贝消息队列的方法

文档序号:6446541阅读:364来源:国知局
专利名称:一种实现通信过程零拷贝消息队列的方法
技术领域
本发明涉及一种实现在操作系统任务或线程间进行通信的方法,具体是一种在通信过程中,实现零拷贝消息队列的方法,适用于在嵌入式实时操作系统任务间,通过消息队列进行通信。
背景技术
随着世界经济进入数字新经济时代,电信技术和信息网络技术得到了前所未有的迅猛发展。通信领域从网络到业务的巨大变化推动着数据业务的持续发展,数据业务的流量在2~3年内可能超过话音业务流量。
基于数据分组交换的业务将在5~10年内覆盖整个传统电信业务。从而在单一话音业务电路交换中的信令流通信方式,变为大量数据业务数据交换中的协议流和信令流通信方式,通信量大大增加,通信速率也在增大,这就对通过操作系统传递控制流数据提出了更高的要求。
现代操作系统常常是通过消息的方式来进行任务间的通信,消息队列提供了一种高级的任务间通信机制,在嵌入式系统中有广泛的用途。但目前的操作系统提供的消息队列在进行消息通信的过程中,为了提供对任务上下文的保护,通常的做法是将发送任务私有空间的消息拷贝到系统缓冲区,再从系统缓冲区拷贝到接收任务的私有空间中,这样在消息收发过程中存在多次的消息内存拷贝,一方面大量消耗系统资源,另一方面通信效率也大大降低了。
1.在嵌入式实时操作系统VxWorks中,系统通过msgQSend()函数发送消息,通过msgQReceive()函数接收消息。一个消息的发送在接收任务等待该消息队列的情况下,要经过一次内存拷贝发送任务的私有空间到接收任务的私有空间。而在接收任务没有等待该消息队列时,要经过二次内存拷贝从发送任务的私有空间到系统消息队列的缓冲区;再从消息队列缓冲区到接收任务的私有空间。如果发送的消息较大,则还必须加大发送任务和接收任务的堆栈空间,否则容易造成堆栈溢出。
2.在通用操作系统如Windows NT中,系统通过PostMessage()函数发送异步消息,通过SendMessage()函数发送同步消息,通过GetMessage()或PeekMessage()接收消息。在windows程序中,当应用程序发送一个消息通知指定的窗口执行一个任务时,PostMessage()函数为该消息创建一个MSG消息结构并将该消息拷贝到消息队列中,而应用程序通过消息循环将该消息取出(从消息队列中拷贝到本地上下文),并派发到相应的窗口进行处理。可见,消息在派发过程中也存在多次内存拷贝问题。
再者,通信领域的应用程序大多是基于消息驱动,对消息队列的操作非常频繁,而目前各种操作系统提供的消息队列调用接口不一致,造成应用程序代码的移植很不方便,可读性也很差。

发明内容
本发明的目的是为了克服了现有操作系统消息队列中存在多次内存拷贝的缺点,提出了一种在通信过程中,实现零拷贝消息队列的方法,以保证消息通信过程中没有内存拷贝。本发明支持紧迫和普通两级消息,并提供了多种查询接口,通过对信号量和互斥机制的适配,可广泛地应用于嵌入式操作系统如VxWorks,pSoS,以及通用操作系统Windows NT,Linux等多种操作系统,屏蔽各种操作系统的差异。
本发明是这样实现的
一种实现通信过程零拷贝消息队列的方法,包括如下步骤第一步 信号量适配创建、获取、释放、删除一个对各种操作系统通用的信号量,包括vxworks,pSos,Windows NT,Linux等操作系统。
第二步 互斥量适配创建、获取、释放、删除一个对各种操作系统通用的互斥量,包括vxworks,pSos,Windows NT,Linux等操作系统。
第三步 系统消息队列池初始化系统初始化时在系统缓冲区中分配一个消息队列池创建整个消息队列的索引信息。
第四步 创建消息队列从消息队列池中查找一个尚未分配的消息队列,返回该消息的编号,用于消息的发送和接收。
第五步 发送消息在指定的消息队列上,发送消息数据,如果是紧迫消息,将该消息添加到消息队列头,普通消息,将该消息添加到消息队列尾,最后返回成功或失败。
第六步 接收消息在指定的消息队列上接收消息,并返回接收缓冲区的指针。如果消息队列为空当超时参数为0,立即返回空指针;当超时参数为-1,任务进入阻塞队列永久等待;当超时参数为其它值,任务延迟一段时间并继续运行。当消息队列非空时,从消息队列头取出一消息并返回到接收缓冲区。
第七步删除消息队列对不用的消息队列需要删除,并释放其占用的内存。删除消息队列是创建消息队列的逆过程,通过对指定的消息队列ID号判断其是否正在使用,若没有使用,删除失败,若正在使用,则将该消息队列中的消息内存释放,清空消息个数,并设置为未用。
第八步查询消息数通过输入索引号获得需要查询的消息队列,并返回其中的消息数。
采用本发明所述的零拷贝消息通信的方法,通过与VxWorks消息队列的对比测试,与现有技术相比,大大提高了通信速率,同时降低了通信过程中的内存占用,节省了宝贵的系统资源。同时由于其支持多种操作系统,因此有利于构建在各种操作系统之上的应用程序的移植。


图1给出的是VxWorks消息队列实现方式;图2给出的是零拷贝消息队列实现原理;图3给出的是零拷贝消息队列的实现流程;图4给出的是创建消息队列流程;图5给出的是发送消息流程;图6给出的是接收消息流程;图7给出的是删除消息队列流程。
具体实施例方式
图1介绍了VxWorks消息队列实现方式,消息队列在初始化时,在系统空间里分配并初始化一个消息队列。以它能够排队的最大的消息数目以及每个消息的最大字节长度作为参数,预先分配足够的缓冲空间。当任务和ISR调用msgQSend()函数向消息队列发送消息时,如果没有任务在等待该队列中的消息,那么该消息进入消息队列的缓冲。如果有任务等待该队列的消息,那么这个消息立即提交给第一个等待的任务。当消息队列已满时,即当队列没有可用缓冲时,发送任务等待一定的超时。当超时为NO_WAIT(0),发送任务立即返回错误。当超时为WAIT_FOREVER(-1),发送任务进入阻塞任务队列。当超时为其他时,发送任务延迟一段时间再继续运行。任务调用msgQReceive()函数从消息队列接收消息。如果队列缓冲中已有可用的消息,那么第一个消息立即出队列,并返回给调用者。如果没有消息可用,调用者将阻塞,进入等待该消息的任务队列中排队。由此可见,在VxWorks中,一个消息的发送在接收任务等待该消息队列的情况下,要经过一次内存拷贝发送任务的私有空间到接收任务的私有空间。而在接收任务没有在该消息队列等待时,要经过二次内存拷贝从发送任务的私有空间到系统消息队列的缓冲区;再从消息队列缓冲区到接收任务的私有空间。
图2介绍了零拷贝消息队列实现原理。零拷贝消息队列是一个由指向消息体数据的指针组成的循环缓冲区,其数据结构包括消息队列的头指针、尾指针、当前消息数目、消息队列的总的消息数目、以及互斥操作信号量、计数信号量等。系统初始化时在系统缓冲区中分配一个消息队列池创建整个消息队列的索引信息。当任务创建一个用于任务间通信的消息队列时,从消息队列池中查找一个尚未分配的消息队列,返回该消息的编号,用于消息的发送和接收。消息发送时,如果是普通消息,发送任务数据的指针挂接到当前消息队列的尾部,如果是紧迫消息,则将该消息数据的指针添加到消息队列的头部。如果到达消息队列的边界,作边界指针调整。发送完毕后释放等待在该消息队列上的信号量,即计数信号量加1。接收消息时,接收任务从队列头取出第一个消息的指针,并将它返回给接收任务缓冲区,同时作适当的指针操作。若消息队列为空,接收等待该消息队列的计数信号量,即计数信号量减1。如果此时计数信号量小于0,则根据接收超时值参数进行相应的处理。由于在消息的发送和接收过程中采用了指针传递,没有进行内存拷贝。
图3介绍了创建消息队列的流程。首先初始化消息队列池,如果消息队列池已经初始化,就不再调用初始化函数。初始化完成后,从系统消息队列池中查找一个尚未使用的消息队列,如果没有找到,则返回一个非法消息队列的索引值;如果找到一个尚未使用的消息队列,则初始化该消息队列的值,包括头指针、尾指针、消息数,创建互斥信号量、创建计数信号量等。这一步操作由于是对全局数据的操作,需要用全局信号量来互斥。初始化该消息队列完成后,返回消息队列的索引。
图4介绍了发送消息流程。首先对输入参数进行效验,非法参数输出打印信息并返回发送失败。接着进入关键代码段保护关键代码段保护可以用开关中断或用信号量来实现,通过宏开关来适配。如果是中断互斥,锁中断;如果是信号量互斥,取信号量。下一步是进行队列的指针操作如果是紧迫消息,将该消息添加到消息队列头;如果是普通消息,将该消息添加到消息队列尾。同时消息队列中的消息数加1。操作完成后退出关键代码段保护如果是中断互斥,打开中断锁。如果是信号量互斥,释放信号量。消息添加到消息队列后,发送任务需要释放等待在该消息队列上的计数信号量,该计数信号量加1,使阻塞任务进入就绪,并让内核运行调度核心。最后返回发送消息成功。
图5介绍了接收消息流程。首先对输入参数进行效验,如果参数非法则返回空指针。首先取得操作该消息队列的指针,然后获取计数信号量,使计数信号量减1,如果该计数信号量小于0,则调用任务将根据超时参数进行处理当超时参数为0,立即返回空指针;当超时参数为-1,任务进入阻塞队列永久等待;当超时参数为其它值,任务延迟一段时间并继续运行。当调用任务恢复运行时,如果消息队列为空,返回空指针,否则进行核心数据操作首先进入关键代码保护,接着进行指针操作,从消息队列头取出一消息,返回给调用者,同时消息队列中的消息数减1,取出消息后退出关键代码保护。最后返回取出的消息。
图6介绍了删除消息队列的流程。删除消息队列是创建消息队列的逆过程,首先取得操作该消息队列的指针,如果该消息队列没有使用,则返回删除错误,否则获得该消息队列的指针,将头指针、尾指针、消息数、最大消息数等值设置为0,同时删除互斥信号量、等待计数信号量,本操作需要做全局数据区的互斥。最后返回删除成功。
图7介绍了如何实现消息队列方案的流程。对前面介绍的方案的8个步骤进行了流程图实现,即信号量适配、互斥量适配、消息队列初始化、创建消息队列、发送消息、接收消息、删除消息队列、查询消息队列等。
权利要求
1.一种实现通信过程零拷贝消息队列的方法,包括如下步骤进行信号量适配创建、获取、释放、删除一个对操作系统通用的信号量;进行互斥量适配创建、获取、释放、删除一个对操作系统通用的互斥量;对系统消息队列池初始化系统初始化时,在系统缓冲区中分配一个消息队列池,以创建整个消息队列的索引信息;创建消息队列从消息队列池中查找一个尚未分配的消息队列,返回该消息的编号,用于消息的发送和接收;发送消息在指定的消息队列上,发送消息数据;接收消息在指定的消息队列上接收消息,并返回接收缓冲区的指针;删除消息队列对不用的消息队列需要删除,并释放其占用的内存;查询消息数通过输入索引号获得需要查询的消息队列,并返回其中的消息数。
2.如权利要求1所述实现零拷贝消息队列的方法,其特征在于所述通用于所适配信号量及互斥量的操作系统包括vxworks,pSos,Windows NT,Linux等。
3.如权利要求1所述实现零拷贝消息队列的方法,其特征在于所述发送消息是紧迫消息,将该消息添加到消息队列头;是普通消息,将该消息添加到消息队列尾。
4.如权利要求1所述实现零拷贝消息队列的方法,其特征在于所述接收消息的消息队列为空超时参数为0,立即返回空指针;超时参数为-1,任务进入阻塞队列永久等待;超时参数为其它值,任务延迟一段时间并继续运行,所述接收消息的消息队列非空,从消息队列头取出一消息并返回到接收缓冲区。
5.如权利要求1所述实现零拷贝消息队列的方法,其特征在于所述删除消息队列用于判断指定消息队列ID号是否使用,若没有使用,删除失败;若正在使用,将该消息队列中的消息内存释放,清空消息个数,并设置为未用。
6.如权利要求1所述实现零拷贝消息队列的方法,其特征在于所述消息队列是一个由指向消息体数据的指针组成的循环缓冲区,其数据结构包括消息队列的头指针、尾指针、当前消息数目、消息队列的总的消息数目、以及互斥操作信号量、计数信号量等。
7.如权利要求1或3所述实现零拷贝消息队列的方法,其特征在于所述发送消息是普通消息,发送任务数据的指针挂接到当前消息队列的尾部;是紧迫消息,则将该消息数据的指针添加到消息队列的头部;到达消息队列的边界,作边界指针调整;发送完毕后释放等待在该消息队列上的信号量,即计数信号量加1。
8.如权利要求1或4所述实现零拷贝消息队列的方法,其特征在于所述接收消息接收任务从消息队列头取出第一个消息的指针,并将它返回给接收任务缓冲区,同时作适当的指针操作,若消息队列为空,接收等待该消息队列的计数信号量,即计数信号量减1;如果此时计数信号量小于0,则根据接收超时值参数进行相应的处理。
9.如权利要求1所述实现零拷贝消息队列的方法,其特征在于所述创建消息队列进一步包括如下步骤初始化消息队列池,从系统消息队列池中查找一个尚未使用的消息队列没有找到,则返回一个非法消息队列的索引值;找到一个尚未使用的消息队列,则初始化该消息队列的值,利用全局信号量来互斥,包括头指针、尾指针、消息数,创建互斥信号量、创建计数信号量等,完成初始化该消息队列,返回消息队列的索引。
10.如权利要求1所述实现零拷贝消息队列的方法,其特征在于所述发送消息进一步包括如下步骤对输入参数进行效验,非法参数输出打印信息并返回发送失败,进入关键代码段保护利用开关中断或用信号量,通过宏开关适配,是中断互斥,锁中断;是信号量互斥,取信号量,进行消息队列的指针操作是紧迫消息,将该消息添加到消息队列头;是普通消息,将该消息添加到消息队列尾,同时消息队列中的消息数加1,退出关键代码段保护是中断互斥,打开中断锁;是信号量互斥,释放信号量,消息添加到消息队列后,发送任务需要释放等待在该消息队列上的计数信号量,该计数信号量加1,使阻塞任务进入就绪,并让内核运行调度核心,返回发送消息成功。
11.如权利要求1所述实现零拷贝消息队列的方法,其特征在于所述接收消息进一步包括如下步骤对输入参数进行效验,参数非法则返回空指针,取得操作该消息队列的指针,然后获取计数信号量,使计数信号量减1,该计数信号量小于0,则调用任务将根据超时参数进行处理;超时参数为0,立即返回空指针;超时参数为-1,任务进入阻塞队列永久等待;超时参数为其它值,任务延迟一段时间并继续运行,调用任务恢复运行,消息队列为空,返回空指针,否则进行核心数据操作首先进入关键代码保护,接着进行指针操作,从消息队列头取出一消息,返回给调用者,同时消息队列中的消息数减1,取出消息后退出关键代码保护,返回取出的消息。
12.如权利要求1所述实现零拷贝消息队列的方法,其特征在于所述删除消息队列进一步包括如下步骤取得操作该消息队列的指针,该消息队列没有使用,则返回删除错误;否则获得该消息队列的指针,做全局数据区的互斥,将头指针、尾指针、消息数、最大消息数等值设置为0,同时删除互斥信号量、等待计数信号量;返回删除成功。
全文摘要
本发明涉及一种在通信过程中,实现零拷贝消息队列的方法。零拷贝消息队列是一个由指向消息体数据的指针组成的循环缓冲区,其数据结构包括消息队列的头指针、尾指针、当前消息数目、消息队列的总的消息数目、以及互斥操作信号量、计数信号量等。本发明克服了现有操作系统消息队列中存在多次内存拷贝的缺点,以保证消息通信过程中没有内存拷贝。可广泛地应用于嵌入式操作系统。通过与VxWorks消息队列的对比测试,大大提高了通信速率,同时降低了通信过程中的内存占用,节省了宝贵的系统资源。同时由于支持多种操作系统,因此有利于构建在各种操作系统之上的应用程序的移植。
文档编号G06F9/06GK1549108SQ0311341
公开日2004年11月24日 申请日期2003年5月7日 优先权日2003年5月7日
发明者谢鑫, 谢 鑫 申请人:中兴通讯股份有限公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1