linux訊息佇列總結

2021-07-09 06:19:10 字數 4385 閱讀 5480

1.訊息佇列簡介

實現linux程序通訊的方式有5種:

--訊號(singal)

--管道(pipe)

--訊息佇列(message)

--訊號量(semaphore)

每種程序通訊方式實現方式和功能不一樣,帶來適用的場景也有所不同,訊息佇列是鍊錶佇列,它通過核心提供乙個struct msqid_ds *msgque[msgmni]向量維護核心的乙個訊息佇列列表,因此linux系統支援的最大訊息佇列數由msgque陣列大小來決定,每乙個msqid_ds表示乙個訊息佇列,並通過msqid_ds.msg_first、msg_last維護乙個先進先出的msg鍊錶佇列,當傳送乙個訊息到該訊息佇列時,把傳送的訊息構造成乙個msg結構物件,並新增到msqid_ds.msg_first、msg_last維護的鍊錶佇列,同樣,接收訊息的時候也是從msg鍊錶佇列尾部查詢到乙個msg_type匹配的msg節點,從鍊錶佇列中刪除該msg節點,並修改msqid_ds結構物件的資料。

2.訊息佇列的資料結構

--1.struct msqid_ds *msgque[msgmni]向量:

msgque[msgmni]是乙個msqid_ds結構的指標陣列,每個msqid_ds結構指標代表乙個系統訊息佇列,msgque[msgmni]的大小為msgmni=128,也就是說系統最多有msgmni=128個訊息佇列

--2.struct msqid_ds

乙個訊息佇列結構

struct msqid_ds 中主要資料成員介紹如下:

struct msqid_ds;

--3.struct msg 訊息節點結構:

msqid_ds.msg_first,msg_last維護的鍊錶佇列中的乙個鍊錶節點

struct msg

--4.msgbuf訊息內容結構:

msg 訊息節點中的訊息體,也是訊息佇列使用程序(訊息佇列傳送接收程序)傳送或者接收的訊息

struct msgbuf

3.訊息佇列的使用

--1.訊息佇列key的獲取:

在程式中若要使用訊息佇列,必須要能知道訊息佇列key,因為應用程序無法直接訪問核心訊息佇列中的資料結構,因此需要乙個訊息佇列的標識,讓應用程序知道當前操作的是哪個訊息佇列,同時也要保證每個訊息佇列key值的唯一性

----a.通過ftok函式獲取

key_t key;

key=ftok(".","a")

該函式通過乙個路徑名稱對映出乙個訊息佇列key(我的理解是使用路徑對映的方式比較容易獲取乙個唯一的訊息佇列key)

----b.直接定義key:

#define msg_key      123456

自定義key的方式要注意避免訊息佇列的重複。

--2.獲取或者開啟乙個訊息佇列

----a.使用說明

qid=msgget(key_t key, int msgflag)

--key:  訊息佇列key

--msgflag:

ipc_private:建立乙個該程序獨佔的訊息佇列,其它程序不能訪問該訊息佇列

ipc_creat:若訊息佇列不存在,建立乙個新的訊息佇列,若訊息佇列存在,返回存在的訊息佇列

ipc_creat | ipc_excl: ipc_excl標誌本身沒有多大意義,與ipc_creat一起使用,保證只建立新的訊息佇列,若對應key的訊息佇列已經存在,則返回錯誤

ipc_nowait:小佇列以非阻塞的方式獲取(若不能獲取,立即返回錯誤)

----b.函式原因

------1)如果key==ipc_private,則申請一塊記憶體,建立乙個新的訊息佇列(資料結構msqid_ds),將其初始化後加入到msgque向量表中的某個空位置處,返回標示符。

------2)在msgque向量表中找鍵值為key的訊息佇列,如果沒有找到,結果有二:

msgflag表示不建立新的佇列,則錯誤返回。

msgflag表示要建立新的佇列(ipc_creat),則建立新訊息佇列,建立過程如1)。

-------3)如果在msgque向量表中找到了鍵值為key的訊息佇列,則有以下情況:

如果msg***表示一定要建立新的訊息佇列而且不允許有相同鍵值的佇列存在,則錯誤返回。

如果找到的佇列是不能用的或已經損壞的佇列,則錯誤返回。

認證和訪問許可權檢查,如果該佇列不允許msg***要求的訪問,則錯誤返回。

正常,返回佇列的識別符號。

--3.傳送乙個訊息到訊息對列

----a.使用說明:

int msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msg***)

------msqid為訊息佇列的qid

------msgp對應訊息內容結構體指標

------msgsz訊息的大小即msgp指標指向的訊息結構體的大小

------msg***訊息標誌

0:忽略該標誌位,以阻塞的方式傳送訊息到訊息佇列

ipc_nowait:以非阻塞的方式傳送訊息,若訊息佇列滿,函式立即返回。

------返回:

0: 成功

-1:非阻塞方式訪問滿訊息佇列返回

eacces:沒有該訊息佇列寫許可權

efault:訊息佇列位址無法獲取

eidrm:訊息佇列已經被刪除

eintr:訊息佇列等待寫入的時候被中斷

enomem:記憶體不夠

----b.函式原理:

1)計算id = (unsigned int) msqid % msgmni,然後根據id在linux系統訊息佇列向量msgque[msgmni]中查詢對應的訊息佇列,並進行認證檢查,合法性檢查

2)如果佇列已滿,以可中斷等待狀態(task_interruptible)將當前程序掛起在wwait等待佇列(傳送訊息等待佇列)上(msgflag==0)。

3)否則 根據msgbuf的大小申請一塊空間,並在其上建立乙個訊息資料結構struct msg(核心空間),將訊息緩衝區中的訊息內容拷貝到該記憶體塊中訊息頭的後面(從使用者空間拷貝到核心空間)。

4)將訊息資料結構加入到訊息佇列的隊尾,修改佇列msqid_ds的相應引數。

5)喚醒在該訊息佇列的rwait程序佇列(讀等待程序佇列)上等待讀的程序,並返回。

--4.從訊息佇列接收乙個訊息到msgbuf*

----a.使用說明

int msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz,long msgtyp, int msg***)

----msqid為訊息佇列的qid

----msgp是接收到的訊息將要存放的緩衝區

----msgsz是訊息的大小

----msgtyp是期望接收的訊息型別

----msg***是標誌

0:表示忽略

ipc_nowait:如果訊息隊列為空,不阻塞等待,返回乙個enomsg

----返回

0:成功

-1:訊息長度大於msgsz

eacces:沒有該訊息佇列讀許可權

efault:訊息佇列位址無法獲取

eidrm:訊息佇列已經被刪除

eintr:訊息佇列等待寫入的時候被中斷

enomem:記憶體不夠

----b.函式原理:

1)計算id = (unsigned int) msqid % msgmni,然後根據id在msgque[msgmni]中查詢對應的訊息佇列,並進行認證檢查,合法性檢查

2)根據msgtyp搜尋訊息佇列,情況有二:

----如果找不到所要的訊息,則以可中斷等待狀態(task_interruptible)將當前程序掛起在rwait等待佇列上

----如果找到所要的訊息,則將訊息從佇列中摘下,調整佇列msqid_ds引數,喚醒該訊息佇列的wwait程序佇列上等待寫的程序,將訊息內容拷貝到使用者空間的訊息緩衝區msgp中,釋放核心中該訊息所占用的空間,返回

--5.訊息的控制

----a.使用說明:

int msgctl (int msqid, int cmd, struct msqid_ds *buf)

------msqid:為訊息佇列的qid

------cmd:為該函式要對訊息佇列執行的操作

ipc_stat:取出訊息佇列的msqid_ds結構體並將引數存入buf所指向的msqid_ds結構物件中

ipc_set:設定訊息佇列的msqid_ds 資料中的msg_perm 成員。設定的值由buf 指向的msqid_ds

結構給出。

ipc_emid:將佇列從系統核心中刪除。

----buf:訊息佇列msqid_ds結構體指標

----b.函式作用

對訊息佇列進行設定以及相關操作,具體操作由cmd指定。

linux訊息佇列 Linux訊息佇列

訊息佇列,unix的通訊機制之一,可以理解為是乙個存放訊息 資料 容器。將訊息寫入訊息佇列,然後再從訊息佇列中取訊息,一般來說是先進先出的順序。可以解決兩個程序的讀寫速度不同 處理資料速度不同 系統耦合等問題,而且訊息佇列裡的訊息哪怕程序崩潰了也不會消失。最簡單的訊息記憶體的使用流程 ftok函式生...

訊息佇列總結

我們可以把訊息佇列看作是乙個存放訊息的容器,當我們需要使用訊息的時候,直接從容器中取出訊息供自己使用即可。訊息佇列是分布式系統中重要的元件之一。使用訊息佇列主要是為了通過非同步處理提高系統效能和削峰 降低系統耦合性。我們知道佇列 queue 是一種先進先出的資料結構,所以消費訊息時也是按照順序來消費...

linux訊息佇列

訊息佇列是核心位址空間中的內部鍊錶,每個訊息佇列都在系統範圍內對應唯一的鍵值,所以,要獲得乙個訊息佇列的描述字,只需提供該訊息佇列的鍵值即可。1 訊息緩衝區結構 存放訊息資料的模板,可在基本定義的基礎上自己定義 在include linux msg.h中宣告,描述如下 struct 可以定義自己的例...