Linux進程通信 | 消息隊列

什么是消息隊列弥咪?

假設你是一個快遞員,你需要將貨物從一個倉庫運到另一個倉庫籍滴。但是你發(fā)現(xiàn)自己的時間不夠用酪夷,需要另外請一個人來幫忙。那么孽惰,你們之間如何進行協(xié)作呢?

一種方式是直接將貨物全部交給對方鸥印,但這樣存在風險:對方可能會出現(xiàn)問題勋功,導致貨物丟失或損壞。

而另一種更安全的方式是库说,你將貨物分批發(fā)送給對方狂鞋,對方再按照你的要求逐批接收貨物。這種方式類似于消息隊列的通信方式潜的。

在 Linux 系統(tǒng)中骚揍,消息隊列是一種 IPC(進程間通信)機制,用于實現(xiàn)不同進程之間的通信啰挪。

簡單地說信不,消息隊列是一個消息的鏈表,消息發(fā)送方將消息發(fā)送到消息隊列中亡呵,消息接收方從隊列中讀取消息抽活。

消息隊列的優(yōu)點和缺點

與其他 IPC 機制相比,消息隊列有以下優(yōu)點:

  • 通過消息隊列可以實現(xiàn)異步通信锰什。
  • 消息隊列可以存儲多個消息下硕,接收方可以按順序逐個讀取消息。
  • 消息隊列的消息長度可以很長汁胆。

但是梭姓,消息隊列也有以下缺點:

  • 消息隊列的消息長度有限制,一般不能超過系統(tǒng)限制的最大值嫩码。
  • 消息隊列需要調(diào)用特殊的系統(tǒng)調(diào)用來讀寫消息誉尖,開銷較大。

消息隊列的創(chuàng)建和使用方法

在Linux中谢谦,可以通過以下系統(tǒng)調(diào)用函數(shù)來創(chuàng)建和使用消息隊列:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgget(key_t key, int msgflg);   // 創(chuàng)建或打開消息隊列
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);   // 向消息隊列發(fā)送消息
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);   // 從消息隊列接收消息
int msgctl(int msqid, int cmd, struct msqid_ds *buf);   // 控制消息隊列

其中释牺,key是用來唯一標識消息隊列的鍵值萝衩,msgflg是創(chuàng)建消息隊列時的選項參數(shù)。在創(chuàng)建消息隊列時没咙,如果該鍵值已經(jīng)存在猩谊,則直接返回該消息隊列的標識符;如果不存在祭刚,則創(chuàng)建一個新的消息隊列牌捷,并返回該消息隊列的標識符。

在使用消息隊列時涡驮,msgsnd函數(shù)用于向消息隊列中發(fā)送消息暗甥,msgrcv函數(shù)用于從消息隊列中接收消息,msgctl函數(shù)用于對消息隊列進行控制捉捅,比如刪除消息隊列等撤防。

消息隊列的發(fā)送和接收示例

下面我們來看一個簡單的示例,展示如何使用消息隊列進行進程間通信棒口。

假設有兩個進程寄月,一個發(fā)送進程和一個接收進程,它們之間需要傳遞一些數(shù)據(jù)无牵。我們通過消息隊列來實現(xiàn)進程間通信漾肮。

首先,我們需要創(chuàng)建一個消息隊列茎毁,然后讓發(fā)送進程向消息隊列中發(fā)送一條消息克懊,接收進程從消息隊列中接收該消息,并進行處理七蜘。

創(chuàng)建消息隊列

我們首先需要創(chuàng)建一個消息隊列谭溉。可以使用msgget函數(shù)來創(chuàng)建消息隊列崔梗。以下是創(chuàng)建消息隊列的示例代碼:

#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    key_t key = ftok("/tmp", 'a'); // 創(chuàng)建一個唯一的key
    int msgid = msgget(key, 0666 | IPC_CREAT); // 創(chuàng)建消息隊列
    if (msgid == -1) {
        perror("msgget");
        exit(EXIT_FAILURE);
    }

    printf("消息隊列創(chuàng)建成功夜只,msgid=%d\n", msgid);

    return 0;
}

在上面的代碼中,我們使用ftok函數(shù)創(chuàng)建一個唯一的key蒜魄,這個key將作為消息隊列的標識符扔亥。然后,我們使用msgget函數(shù)創(chuàng)建消息隊列谈为。如果創(chuàng)建成功旅挤,msgget函數(shù)將返回一個消息隊列ID(msgid),否則將返回-1伞鲫。在本例中粘茄,如果創(chuàng)建消息隊列失敗,我們將輸出錯誤消息并退出程序。

發(fā)送消息

接下來柒瓣,我們將使用msgsnd函數(shù)向消息隊列發(fā)送一些消息儒搭。以下是一個發(fā)送消息的示例代碼:

// sendmsg.c

#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    long type;
    char text[100];
} message_t;

int main()
{
    key_t key = ftok("/tmp", 'a'); // 創(chuàng)建一個唯一的key
    int msgid = msgget(key, 0666 | IPC_CREAT); // 創(chuàng)建消息隊列
    if (msgid == -1) {
        perror("msgget");
        exit(EXIT_FAILURE);
    }

    message_t message;
    message.type = 1;
    strcpy(message.text, "Hello, World!");
    int result = msgsnd(msgid, &message, sizeof(message.text), 0);
    if (result == -1) {
        perror("msgsnd");
        exit(EXIT_FAILURE);
    }

    printf("消息發(fā)送成功,text=%s\n", message.text);

    return 0;
}

在上面的代碼中芙贫,我們定義了一個message_t結(jié)構(gòu)體搂鲫,它包含一個長整型變量和一個字符串數(shù)組。長整型變量將用于指定消息類型磺平,而字符串數(shù)組將包含消息正文魂仍。然后,我們使用msgsnd函數(shù)將消息發(fā)送到隊列拣挪。在本例中擦酌,我們發(fā)送的消息類型為1,消息正文為"Hello, World!"菠劝。

接收消息

最后赊舶,我們將使用msgrcv函數(shù)從消息隊列接收我們之前發(fā)送的消息。以下是一個接收消息的示例代碼:

// rsvmsg.c

#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    long type;
    char text[100];
} message_t;

int main()
{
    key_t key = ftok("/tmp", 'a'); // 創(chuàng)建一個唯一的key
    int msgid = msgget(key, 0666 | IPC_CREAT); // 創(chuàng)建消息隊列
    if (msgid == -1) {
        perror("msgget");
        exit(EXIT_FAILURE);
    }

    message_t message;
    int result = msgrcv(msgid, &message, sizeof(message.text), 1, 0);
    if (result == -1) {
        perror("msgrcv");
        exit(EXIT_FAILURE);
    }

    printf("消息接收成功赶诊,text=%s\n", message.text);

    return 0;
}

效果演示

編譯上面的sendmsg.c 和 rsvmsg.c文件锯岖,得到一個兩個程序:sendmsg和rsvmsg。

  • 先運行sendmsg甫何,后運行rsvmsg
[wayne@wayne:~] ./sendmsg
消息發(fā)送成功,text=Hello, World!
[wayne@wayne:~] ./rsvmsg
消息接收成功遇伞,text=Hello, World!
  • 先運行rsvmsg辙喂,后運行sendmsg
[wayne@wayne:~] ./rsvmsg

此時rsvmsg會阻塞在這里,等待消息

[wayne@wayne:~] ./sendmsg
消息發(fā)送成功鸠珠,text=Hello, World!

sendmsg發(fā)送消息后巍耗,rsvmsg進程,收到消息渐排,打印消息

消息接收成功炬太,text=Hello, World!

小結(jié)

總的來說,Linux 消息隊列是一種高效的進程間通信機制驯耻,它可以在多個進程之間共享亲族,允許進程異步地發(fā)送和接收消息。

以上可缚,如果覺得對你有幫助霎迫,點個贊再走吧,這樣@知微之見也有更新下去的動力帘靡!

也歡迎私信我知给,一起交流!

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市涩赢,隨后出現(xiàn)的幾起案子戈次,更是在濱河造成了極大的恐慌,老刑警劉巖筒扒,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怯邪,死亡現(xiàn)場離奇詭異,居然都是意外死亡霎肯,警方通過查閱死者的電腦和手機擎颖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來观游,“玉大人搂捧,你說我怎么就攤上這事《疲” “怎么了允跑?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長搪柑。 經(jīng)常有香客問我聋丝,道長,這世上最難降的妖魔是什么工碾? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任弱睦,我火速辦了婚禮,結(jié)果婚禮上渊额,老公的妹妹穿的比我還像新娘况木。我一直安慰自己,他們只是感情好旬迹,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布火惊。 她就那樣靜靜地躺著,像睡著了一般奔垦。 火紅的嫁衣襯著肌膚如雪屹耐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天椿猎,我揣著相機與錄音惶岭,去河邊找鬼。 笑死鸵贬,一個胖子當著我的面吹牛俗他,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播阔逼,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼兆衅,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起羡亩,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤摩疑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后畏铆,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雷袋,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年辞居,在試婚紗的時候發(fā)現(xiàn)自己被綠了楷怒。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡瓦灶,死狀恐怖鸠删,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情贼陶,我是刑警寧澤刃泡,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站碉怔,受9級特大地震影響烘贴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜撮胧,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一桨踪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧芹啥,春花似錦馒闷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽逛薇。三九已至捺疼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間永罚,已是汗流浹背啤呼。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留呢袱,地道東北人官扣。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像羞福,于是被迫代替她去往敵國和親惕蹄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容