新聞中心
隨著計算機技術的不斷發(fā)展,軟件開發(fā)已經成為人們工作中的重要組成部分,而在軟件開發(fā)中,通信模塊一直是一個核心的模塊,它可以實現各個模塊之間的數據傳輸和交換,使整個系統(tǒng)得以協(xié)同運作。針對Linux系統(tǒng)開發(fā)的通信模塊中,消息隊列是一種實現通信的有效方式,而Linux消息隊列的封裝則是讓這種方式更具備高效和穩(wěn)定性的關鍵。

創(chuàng)新互聯(lián)-專業(yè)網站定制、快速模板網站建設、高性價比開福網站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式開福網站制作公司更省心,省錢,快速模板網站建設找我們,業(yè)務覆蓋開福地區(qū)。費用合理售后完善,十多年實體公司更值得信賴。
一、Linux消息隊列的基本概念
在Linux系統(tǒng)中,消息隊列是一種進程間通信方式,它允許數據由一個進程寫入到隊列中,然后由另一個進程從隊列中讀取數據。消息隊列是一種非常高效的通信方式,它避免了進程之間頻繁地創(chuàng)建或銷毀共享內存或管道等等通信方式的操作,同時也能夠避免數據的丟失或錯誤。
二、Linux消息隊列的使用優(yōu)勢
相對于其他的進程間通信方式,Linux消息隊列有以下幾個使用優(yōu)勢:
1.高效穩(wěn)定。消息隊列是一種快速有效的通信方式,能夠滿足多個進程同時進行通信的需求,而且由于消息隊列具有自動化管理的性質,所以啟動和關閉的時間相對于其他通信方式更快。
2.可靠性強。消息隊列中的每個消息都被賦予了一個類型值,并且能夠自動標識一個消息的優(yōu)先級,因此,消息的傳遞過程不會發(fā)生阻塞或死鎖的現象。
3.方便易用。Linux系統(tǒng)提供了一套完整的消息隊列API,程序員只需要按照這些API的規(guī)范來編寫程序就可以輕松實現消息隊列的創(chuàng)建、打開、讀寫等操作。另外,在Linux系統(tǒng)中,每個消息隊列都具有一個獨特的標識符和一個名稱,這些屬性可以方便地組織進程之間的通信關系。
4.能夠支持多種數據類型。消息隊列不僅可以傳遞簡單的字符串類型的數據,也可以支持結構體、自定義數據類型等多種類型的數據。
三、Linux消息隊列的封裝實現
基于以上的有關Linux消息隊列的基本概念和使用優(yōu)勢,對Linux消息隊列的封裝實現具體實現流程如下:
1.定義消息隊列的數據格式。由于消息隊列可以支持多種數據類型,因此,在封裝的時候需要先定義數據類型,以便后續(xù)的消息寫入和讀取操作??梢允褂媒Y構體來定義消息格式,結構體中需要包含消息定位符、消息類型、消息實體等信息。
2.創(chuàng)建消息隊列。在Linux系統(tǒng)中,可以使用Linux消息隊列API來創(chuàng)建消息隊列。消息隊列的創(chuàng)建分為兩個步驟:首先是創(chuàng)建一個消息隊列連接對象,然后使用該連接對象創(chuàng)建一個具體的消息隊列。創(chuàng)建消息隊列時需要指定一些參數,例如消息隊列的更大消息數和消息大小、隊列的相關權限、消息隊列的名稱等。
3.消息隊列的寫入。在Linux系統(tǒng)中,可以使用msgsnd函數來將消息寫入消息隊列。msgsnd函數需要指定要寫入的消息隊列的標識符、消息的類型、具體的消息內容以及消息的長度等參數。在寫入消息之前,需要先將消息格式化為上述定義的消息格式,以便方便之后的讀取操作。
4.消息隊列的讀取。在Linux系統(tǒng)中,可以使用msgrcv函數來從消息隊列中讀取消息。msgrcv的三個參數分別為:消息隊列標識符、消息的類型以及接收消息的位置和大小。當消息隊列中沒有需要讀取的消息時,msgrcv函數會自動阻塞,直到有新的消息到達。
5.消息隊列的刪除。在Linux系統(tǒng)中,可以使用msgctl函數來刪除消息隊列。msgctl函數需要指定消息隊列的標識符和要進行的操作,例如銷毀整個消息隊列或刪除消息隊列中的所有消息。
四、Linux消息隊列封裝的使用場景
Linux消息隊列封裝是一個高效穩(wěn)定的通信利器,它的使用場景非常廣泛。以下是一些常見的使用場景:
1.分布式系統(tǒng)中,各個節(jié)點之間需要進行通信。
2.多線程程序中,線程之間需要進行數據交換和同步。
3.網絡通信程序中,需要進行消息傳遞和控制。
Linux消息隊列封裝是一種高效穩(wěn)定的通信方式,在實際應用中具有廣泛的應用前景。掌握了Linux消息隊列的封裝技術,能夠有效提高程序的可讀性和可維護性,為自己的工作帶來更多的收益和成就。
相關問題拓展閱讀:
- linux 進程間通信的幾種方式
- linux系統(tǒng)怎么封裝
- 一個Linux多進程編程?
linux 進程間通信的幾種方式
1管道(Pipe)及有名管道(named pipe):管道可用于具有親緣關系進程間的通信,有名管道克服了管道沒有名字的限制,因此,除具有管道所具有的功能外,它還允許無親緣關系進程間的通信;
2信號(Signal):信號是比較復雜的通信方式,用于通知接受進程有某種事件發(fā)生,除了用于進程間通信外,進程還可以發(fā)送信號給進程本身;linux除了支持Unix早期信號語義函數sigal外,還支持語義符合Posix.1標準的信號函數sigaction(實際上,該函數是模洞基于BSD的,BSD為了實現可靠信號機制,又能夠統(tǒng)一對外接口,用sigaction函數重新實現了signal函數);
3報文(Message)隊列(消息隊列):消息隊列是消旦戚枯息的鏈接表,包括Posix消息隊列system V消息隊列。有足夠權限的進程可以向隊列中添加消息,被賦予讀權限的進程則可以讀走隊列中的消息。消息隊列克服了信號承載信息量少,管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺點。
4共享內存:使得多仔稿個進程可以訪問同一塊內存空間,是最快的可用IPC形式。是針對其他通信機制運行效率較低而設計的。往往與其它通信機制,如信號量結合使用,來達到進程間的同步及互斥。
5信號量(semaphore):主要作為進程間以及同一進程不同線程之間的同步手段。
6套接口(Socket):更為一般的進程間通信機制,可用于不同機器之間的進程間通信。起初是由Unix系統(tǒng)的BSD分支開發(fā)出來的,但現在一般可以移植到其它類Unix系統(tǒng)上:Linux和System V的變種都支持套接字。
之一種:管道通信
兩個進程利用管道進行通信時,發(fā)送信息的進程稱為寫進程;接收信息的進程稱為讀進程。管道通信方式的中間介質就是文件,通常稱這種文件為管道文件,它就像管道一樣將一個寫進程和一個讀進程連接在一起,實現兩個進程之間的通信。寫進程通過寫入端往管道文件中寫入信息;讀進程通過讀出端從管道文件中讀取信息。兩個進程協(xié)調不斷地進行寫和讀,便會構成雙方通過管道傳遞信息的流水線。
第二種:消息緩沖通信
多個獨立的進程之間可以通過消息緩沖機制來相互通信。這種通銀缺芹信的實現是以消息緩沖區(qū)為中間介質,通信雙方的發(fā)送和接收操作均以消息為單位鋒畢。在存儲器中,消息緩沖區(qū)被組織成隊列,通常稱之為消息隊列。消息隊列一旦創(chuàng)建后即可由多進程共享,發(fā)送消息的進程可以在任意時刻發(fā)送任意個扮缺消息到指定的消息隊列上,并檢查是否有接收進程在等待它所發(fā)送的消息。若有則喚醒它,而接收消息的進程可以在需要消息的時候到指定的消息隊列上獲取消息,如果消息還沒有到來,則轉入睡眠等待狀態(tài)。
第三種:共享內存通信
針對消息緩沖需要占用CPU進行消息復制的缺點,OS提供了一種進程間直接進行數據交換的通信方式。共享內存,顧名思義這種通信方式允許多個進程在外部通信協(xié)議或同步,互斥機制的支持下使用同一個內存段進行通信,它是一種最有效的數據通信方式,其特點是沒有中間環(huán)節(jié),直接將共享的內存頁面通過附接映射到相互通信的進程各自的虛擬地址空間中,從而使多個進程可以直接訪問同一個物理內存頁面。
linux系統(tǒng)怎么封裝
先將你的電腦安裝LINUX系統(tǒng),然后安裝好軟件,再使用一鍵封裝則手軟件進行封裝就亂瞎是ISO安裝盤了,如果你刻嘩盯空錄成光盤起碼也能賣最少5塊錢了,呵呵
一個Linux多進程編程?
1 引言
對于沒有接觸過Unix/Linux操作系統(tǒng)的人來說,fork是最難理解的概念之一:它執(zhí)行一次卻返回兩個值。fork函數是Unix系統(tǒng)最杰出的成就之一,它是七十年代UNIX早期的開發(fā)者經過長期在理論和實踐上的艱苦探索后取得的成果,一方面,它使操作系統(tǒng)在進程管理上付出了最小的代價,另一方面,又為程序員提供了一個簡潔明了的多進程方法。與DOS和早期的Windows不同,Unix/Linux系統(tǒng)是真正實現多任務操作的系統(tǒng),可以說,不使用多進程編程,就不能算是真正的Linux環(huán)境下編程。
多線程程序設計的概念早在六十年代就被提出,但直到八十年代中期,Unix系統(tǒng)中才引入多線程機制,如今,由于自身的許多優(yōu)點,多線程編程已經得到了廣泛的應用。
下面,我們將介紹在Linux下編寫多進程和多線程程序的一些初步知識。
2 多進程編程
什么是一個漏態(tài)耐進程?進程這個概念是針對系統(tǒng)而不是針對用戶的,對用戶來說,他面對的概念是程序。當用戶敲入命令執(zhí)行一個程序的時候,對系統(tǒng)而言,它將啟動一個進程。但和程序不同的是,在這個進程中,系統(tǒng)可能需要再啟動一個或多個進程來完成獨立的多個任務。多進程編程的主要內容包括進程控制和進程間通信,在了解這些之前,我們先要簡單知道進程的結構。
2.1 Linux下進程的結構
Linux下一個進程在內存里有三部分的數據,就是”代碼段”、”堆棧段”和”數據段”。其實學過匯編語言的人一定知道,一般的CPU都有上述三種段寄存器,以方便操作系統(tǒng)的運行。這三個部分也是構成一個完整的執(zhí)行序列的必要的部分。
“代碼段”,顧名思義,就是存放了程序代碼的數據,假如機器中有數個進程運行相同的一個程序,那么它們就可以使用相同的代碼段?!倍褩6巍贝娣诺木褪亲映绦虻姆祷氐刂?、子程序的參數以及程序的局部變量。而數據段則存放程序的全局變量,常數以及動態(tài)數據分配的數據空間(比如用malloc之類的函數取得的空間)。這其中有許多細節(jié)問題,這里限于篇幅就不多介紹了。系統(tǒng)如果同時運行數個相同的程序,它們之間就不能使用同一個堆棧段和數據段。
2.2 Linux下的進程控制
在傳統(tǒng)的Unix環(huán)境下,有兩個基本的操作用于創(chuàng)建和修改進程:函數fork( )用來創(chuàng)建一個新的進程,該進程幾乎是當前進程的一個完全拷貝;函數族exec( )用來啟動另外的進程以取代當前運行的進程。Linux的進程控制和傳統(tǒng)的Unix進程控制基本一致,只在一些細節(jié)的地方有些區(qū)別,例如在Linux系統(tǒng)中調用vfork和fork完全相同,而在有些版本的Unix系統(tǒng)中,vfork調用有不同的功能。由于這些差別幾乎不影響我們大多數的編程,在這里我們不予考慮。
2.2.1 fork( )
fork在英文中是”分叉”的意思。為什么取這個名字呢返春?因為一個進程在運行中,如果使用了fork,就產生了另一個進程,于是進程就”分叉”了,所以這個名字取得很形象。下面就看看如何具體使用fork,這段程序演示了使用fork的基本框閉櫻架:
void main(){
int i;
if ( fork() == 0 ) {
/* 子進程程序 */
for ( i = 1; i ” );
fgets( command, 256, stdin );
command = 0;
if ( fork() == 0 ) {
/* 子進程執(zhí)行此命令 */
execlp( command, command );
/* 如果exec函數返回,表明沒有正常執(zhí)行命令,打印錯誤信息*/
perror( command );
exit( errorno );
}
else {
/* 父進程, 等待子進程結束,并打印子進程的返回值 */
wait ( &rtn );
printf( ” child process return %d\n”,. rtn );
}
}
}
此程序從終端讀入命令并執(zhí)行之,執(zhí)行完成后,父進程繼續(xù)等待從終端讀入命令。熟悉DOS和WINDOWS系統(tǒng)調用的朋友一定知道DOS/WINDOWS也有exec類函數,其使用方法是類似的,但DOS/WINDOWS還有spawn類函數,因為DOS是單任務的系統(tǒng),它只能將”父進程”駐留在機器內再執(zhí)行”子進程”,這就是spawn類的函數。WIN32已經是多任務的系統(tǒng)了,但還保留了spawn類函數,WIN32中實現spawn函數的方法同前述UNIX中的方法差不多,開設子進程后父進程等待子進程結束后才繼續(xù)運行。UNIX在其一開始就是多任務的系統(tǒng),所以從核心角度上講不需要spawn類函數。
在這一節(jié)里,我們還要講講system()和popen()函數。system()函數先調用fork(),然后再調用exec()來執(zhí)行用戶的登錄shell,通過它來查找可執(zhí)行文件的命令并分析參數,最后它么使用wait()函數族之一來等待子進程的結束。函數popen()和函數system()相似,不同的是它調用pipe()函數創(chuàng)建一個管道,通過它來完成程序的標準輸入和標準輸出。這兩個函數是為那些不太勤快的程序員設計的,在效率和安全方面都有相當的缺陷,在可能的情況下,應該盡量避免。
2.3 Linux下的進程間通信
詳細的講述進程間通信在這里絕對是不可能的事情,而且筆者很難有信心說自己對這一部分內容的認識達到了什么樣的地步,所以在這一節(jié)的開頭首先向大家推薦著名作者Richard Stevens的著名作品:《Advanced Programming in the UNIX Environment》,它的中文譯本《UNIX環(huán)境高級編程》已有機械工業(yè)出版社出版,原文精彩,譯文同樣地道,如果你的確對在Linux下編程有濃厚的興趣,那么趕緊將這本書擺到你的書桌上或計算機旁邊來。說這么多實在是難抑心中的景仰之情,言歸正傳,在這一節(jié)里,我們將介紹進程間通信最最初步和最最簡單的一些知識和概念。
首先,進程間通信至少可以通過傳送打開文件來實現,不同的進程通過一個或多個文件來傳遞信息,事實上,在很多應用系統(tǒng)里,都使用了這種方法。但一般說來,進程間通信(IPC:InterProcess Communication)不包括這種似乎比較低級的通信方法。Unix系統(tǒng)中實現進程間通信的方法很多,而且不幸的是,極少方法能在所有的Unix系統(tǒng)中進行移植(唯一一種是半雙工的管道,這也是最原始的一種通信方式)。而Linux作為一種新興的操作系統(tǒng),幾乎支持所有的Unix下常用的進程間通信方法:管道、消息隊列、共享內存、信號量、套接口等等。下面我們將逐一介紹。
2.3.1 管道
管道是進程間通信中最古老的方式,它包括無名管道和有名管道兩種,前者用于父進程和子進程間的通信,后者用于運行于同一臺機器上的任意兩個進程間的通信。
無名管道由pipe()函數創(chuàng)建:
#include
int pipe(int filedis);
參數filedis返回兩個文件描述符:filedes為讀而打開,filedes為寫而打開。filedes的輸出是filedes的輸入。下面的例子示范了如何在父進程和子進程間實現通信。
#define INPUT 0
#define OUTPUT 1
void main() {
int file_descriptors;
/*定義子進程號 */
pid_t pid;
char buf;
int returned_count;
/*創(chuàng)建無名管道*/
pipe(file_descriptors);
/*創(chuàng)建子進程*/
if((pid = fork()) == -1) {
printf(“Error in fork\n”);
exit(1);
}
/*執(zhí)行子進程*/
if(pid == 0) {
printf(“in the spawned (child) process…\n”);
/*子進程向父進程寫數據,關閉管道的讀端*/
close(file_descriptors);
write(file_descriptors, “test data”, strlen(“test data”));
exit(0);
} else {
/*執(zhí)行父進程*/
printf(“in the spawning (parent) process…\n”);
/*父進程從管道讀取子進程寫的數據,關閉管道的寫端*/
close(file_descriptors);
returned_count = read(file_descriptors, buf, sizeof(buf));
printf(“%d bytes of data received from spawned process: %s\n”,
returned_count, buf);
}
}
在Linux系統(tǒng)下,有名管道可由兩種方式創(chuàng)建:命令行方式mknod系統(tǒng)調用和函數mkfifo。下面的兩種途徑都在當前目錄下生成了一個名為myfifo的有名管道:
方式一:mkfifo(“myfifo”,”rw”);
方式二:mknod myfifo p
生成了有名管道后,就可以使用一般的文件I/O函數如open、close、read、write等來對它進行操作。下面即是一個簡單的例子,假設我們已經創(chuàng)建了一個名為myfifo的有名管道。
/* 進程一:讀有名管道*/
#include
#include
void main() {
FILE * in_file;
int count = 1;
char buf;
in_file = fopen(“mypipe”, “r”);
if (in_file == NULL) {
printf(“Error in fdopen.\n”);
exit(1);
}
while ((count = fread(buf, 1, 80, in_file)) > 0)
printf(“received from pipe: %s\n”, buf);
fclose(in_file);
}
/* 進程二:寫有名管道*/
#include
#include
void main() {
FILE * out_file;
int count = 1;
char buf;
out_file = fopen(“mypipe”, “w”);
if (out_file == NULL) {
printf(“Error opening pipe.”);
exit(1);
}
sprintf(buf,”this is test data for the named pipe example\n”);
fwrite(buf, 1, 80, out_file);
fclose(out_file);
}
2.3.2 消息隊列
消息隊列用于運行于同一臺機器上的進程間通信,它和管道很相似,事實上,它是一種正逐漸被淘汰的通信方式,我們可以用流管道或者套接口的方式來取代它,所以,我們對此方式也不再解釋,也建議讀者忽略這種方式。
2.3.3 共享內存
共享內存是運行在同一臺機器上的進程間通信最快的方式,因為數據不需要在不同的進程間復制。通常由一個進程創(chuàng)建一塊共享內存區(qū),其余進程對這塊內存區(qū)進行讀寫。得到共享內存有兩種方式:映射/dev/mem設備和內存映像文件。前一種方式不給系統(tǒng)帶來額外的開銷,但在現實中并不常用,因為它控制存取的將是實際的物理內存,在Linux系統(tǒng)下,這只有通過限制Linux系統(tǒng)存取的內存才可以做到,這當然不太實際。常用的方式是通過shmXXX函數族來實現利用共享內存進行存儲的。
首先要用的函數是shmget,它獲得一個共享存儲標識符。
#include
#include
#include
int shmget(key_t key, int size, int flag);
這個函數有點類似大家熟悉的malloc函數,系統(tǒng)按照請求分配size大小的內存用作共享內存。Linux系統(tǒng)內核中每個IPC結構都有的一個非負整數的標識符,這樣對一個消息隊列發(fā)送消息時只要引用標識符就可以了。這個標識符是內核由IPC結構的關鍵字得到的,這個關鍵字,就是上面之一個函數的key。數據類型key_t是在頭文件sys/types.h中定義的,它是一個長整形的數據。在我們后面的章節(jié)中,還會碰到這個關鍵字。
當共享內存創(chuàng)建后,其余進程可以調用shmat()將其連接到自身的地址空間中。
void *shmat(int shmid, void *addr, int flag);
shmid為shmget函數返回的共享存儲標識符,addr和flag參數決定了以什么方式來確定連接的地址,函數的返回值即是該進程數據段所連接的實際地址,進程可以對此進程進行讀寫操作。
關于linux封裝消息隊列的介紹到此就結束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關注本站。
香港服務器選創(chuàng)新互聯(lián),2H2G首月10元開通。
創(chuàng)新互聯(lián)(www.cdcxhl.com)互聯(lián)網服務提供商,擁有超過10年的服務器租用、服務器托管、云服務器、虛擬主機、網站系統(tǒng)開發(fā)經驗。專業(yè)提供云主機、虛擬主機、域名注冊、VPS主機、云服務器、香港云服務器、免備案服務器等。
網站名稱:Linux消息隊列封裝:高效穩(wěn)定通訊利器(linux封裝消息隊列)
本文網址:http://www.5511xx.com/article/dphijoi.html


咨詢
建站咨詢
