專利名稱:一種實現通信過程零拷貝消息隊列的方法
技術領域:
本發明涉及一種實現在操作系統任務或線程間進行通信的方法,具體是一種在通信過程中,實現零拷貝消息隊列的方法,適用于在嵌入式實時操作系統任務間,通過消息隊列進行通信。
背景技術:
隨著世界經濟進入數字新經濟時代,電信技術和信息網絡技術得到了前所未有的迅猛發展。通信領域從網絡到業務的巨大變化推動著數據業務的持續發展,數據業務的流量在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日
發明者謝鑫, 謝 鑫 申請人:中興通訊股份有限公司