程序間通訊(二) 訊息佇列

2021-08-15 10:51:09 字數 3654 閱讀 1126

我會用幾篇部落格總結一下在linux中程序之間通訊的幾種方法,我會把這個開頭的摘要部分在這個系列的每篇部落格中都打出來

程序之間通訊的方式

程序間通訊(一)—管道傳送門:

程序間通訊(三)—訊號量傳送門:

程序間通訊(四)—共享儲存區傳送門:

程序間通訊(五)—訊號傳送門:

這次主要寫的是訊息佇列,之前講過的管道和訊息佇列在本質上就有很大的區別,管道是乙個檔案,而訊息佇列是乙個資料結構(類似於鍊錶)。這說明了,管道檔案是存放在磁碟上的,關機也會存在(尤其是命名管道更為顯而易見,你不刪除他他就擱那呆著),而訊息佇列是存在於核心中的記憶體,顯而易見,關機就沒了。

更關鍵的是,記憶體他快呀,比磁碟i/o快多了,為啥要用那麼慢的管道。而且訊息佇列是可以直接完成沒有親緣關係的程序之間的通訊的。但是結構比起管道要複雜,用到了很多結構體。內容有些多。先寫一下和管道的主要區別,可以更直觀的進行對比

那麼從頭開始吧:

在c庫函式中有乙個系統呼叫可以建立乙個訊息佇列,那就是msgget,跟這個函式有關的其他函式也會一併給出來

返回值,成功返回標誌訊息佇列的唯一的乙個int,失敗返回-1

相關函式就這麼多,到這裡就可以開心的建立乙個新的訊息佇列了,那麼怎麼看我們建立出來的訊息佇列呢?怎麼銷毀他呢?

先用命令看一下,使用ipcs -q就可檢視訊息佇列的狀態,這裡我建立了乙個訊息佇列,下面來銷毀它

使用ipcrm -q msqid就可以銷毀乙個訊息佇列,我已經把剛才建立的訊息佇列銷毀了

那麼如何通過c函式銷毀乙個訊息佇列?使用msgctl函式

這裡提一下,訊息佇列的乙個缺點,這裡說到ipc_set對訊息佇列的初始化,就是說訊息佇列的建立和初始化是分開的,這樣設計不是很好,因為有執行緒安全的問題,當乙個執行緒建立了訊息佇列還沒初始化,另乙個執行緒直接開始執行訪問的操作就很尷尬了

這裡說錯了!我把訊號量的缺點說成是訊息佇列的了!現在取消了,真是對不起!!!

struct msginfo ;
提到使用訊息佇列無非就是訊息的寫入和訊息的讀出,這涉及兩個函式和乙個結構體

先說傳送函式

在列接受函式之前必須把結構體放出來,不然下面就懵逼了

struct msgbuf ;
mtype講起,因為佇列是好多程序(或者說是執行緒)都拿來用的,比如4個程序共用乙個訊息佇列,兩兩之間進行通訊,就有必要標識哪兩個程序是一組的,哪塊資料是屬於你們組的,不能亂拿是不是,這個mtype就是用來標識的,但是一定要大於0,我一開始設定為0一直報引數錯誤,查了文件才發現自己蠢了。。。

mtext存放的就是你要傳輸的資料了,怎麼大小只有1?當然不能只有1,我自己寫的msgbuf就有1024長度。。。所以還是自己寫爽啊

可以說接受函式了

成功返回長度,失敗返回-1

事已至此,基本操作就說完了,廢話少說,show me the code

我的程式分為comm.h(公共標頭檔案)  comm.c(封裝基本函式) server.c(簡易伺服器端) client.c(簡易客戶端)一共4個檔案

完成了伺服器端和客戶端的簡單通訊(回合制聊天(誤))

comm.h

#include #include #include #include #include #include #include #include #include #define _path_name_ "/tmp"

#define _proj_id_ 0x666

#define _size_ 1024

static int comm_create_msg_set(int flags);

int create_msg_set();

int get_msg_set();

void destory_msg_set(int msg_id);

void send_msg(int msg_id,long msgtype,char * buf);

void receive_msg(int msg_id,long msgtype,char *buf);

struct msgbuf

;

comm.c

#include #include #include #include #include #include #include #include #include #define _path_name_ "/tmp"

#define _proj_id_ 0x666

#define _size_ 1024

static int comm_create_msg_set(int flags);

int create_msg_set();

int get_msg_set();

void destory_msg_set(int msg_id);

void send_msg(int msg_id,long msgtype,char * buf);

void receive_msg(int msg_id,long msgtype,char *buf);

struct msgbuf

;

server.c

#include "comm.h"

long c_type=1;

long s_type=22;

int main()

printf("client # %s\n",buf);

printf("clent say done ! please input:");

fflush(stdout);

memset(buf,'\0',sizeof(buf));

send_msg(msg_id,c_type,buf);

}destory_msg_set(msg_id);

return 0;

}

client.c

#include "comm.h"  

long c_type=1;

long s_type=2;

int main()

memset(buf,'\0',sizeof(buf));

receive_msg(msg_id,c_type,buf);

printf("server # %s\n",buf);

printf("server say done ! please input:");

fflush(stdout);

}return 0;

}

程序間通訊 訊息佇列(二)

例項 模擬經緯度的收發工作。採用訊息佇列的方式處理 專案中涉及2個不相關程序a和程序b 假設你是專案的程序a編寫者,你負責把程序a的經緯度傳送到 第三方導航軟體中 導航定位 程序b 程序a每2秒傳送一次經緯度,程序b每3秒接受一次經緯度並列印顯示。上海預設是北緯東經 資料體 body 協議 int ...

程序間通訊(二) 訊息佇列

訊息佇列是作業系統為兩個無關程序準備的通訊方式,每個訊息佇列都有乙個他自己的id我們用來標識訊息佇列 訊息佇列的不足就是我們傳送訊息的 最大長度有限制,並且作業系統提供的 訊息佇列的個數也是有限的 此id用如下函式建立 此函式中的path為乙個路徑,講道理這個路徑其實可以隨便定義,一般定義成當前目錄...

程序間訊息佇列通訊

要保證server能夠接收client的訊息,就必須保證server的生成的msg的識別符號是一樣的,也就是兩個用的key是必須一樣的。msglucy.c include include include include include include include include include ...