日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

jmstemplate 获取队列id_学习Linux(38)消息队列

發(fā)布時間:2025/3/12 linux 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jmstemplate 获取队列id_学习Linux(38)消息队列 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

消息隊列、共享內存 和 信號量?被統(tǒng)稱為 system-V IPC,V 是羅馬數(shù)字 5,是 Unix 的AT&T 分支的其中一個版本,一般習慣稱呼他們?yōu)?IPC 對象,這些對象的操作接口都比較類似,在系統(tǒng)中他們都使用一種叫做 key 的鍵值來唯一標識,而且他們都是“持續(xù)性”資源——即他們被創(chuàng)建之后,不會因為進程的退出而消失,而會持續(xù)地存在,除非調用特殊的函數(shù)或者命令刪除他們。

消息隊列與信號的對比:

·?信號承載的信息量少,而消息隊列可以承載大量的數(shù)據(jù)

消息隊列與管道的對比:

·?消息隊列跟命名管道有不少的相同之處,通過與命名管道一樣,消息隊列進行通信的進程可以是不相關的進程,同時它們都是通過發(fā)送和接收的方式來傳遞數(shù)據(jù)的。在命名管道中,發(fā)送數(shù)據(jù)用write(),接收數(shù)據(jù)用read(),則在消息隊列中,發(fā)送數(shù)據(jù)用msgsnd(),接收數(shù)據(jù)用msgrcv()。它們對每個數(shù)據(jù)都有一個最大長度的限制。

·?消息隊列也可以獨立于發(fā)送和接收進程而存在,在進程終止時,消息隊列及其內容并不會被刪除。

·?管道只能承載無格式字節(jié)流,消息隊列提供有格式的字節(jié)流,可以減少了開發(fā)人員的工作量。

·?消息隊列是面向記錄的,其中的消息具有特定的格式以及特定的優(yōu)先級,接收程序可以通過消息類型有選擇地接收數(shù)據(jù),而不是像命名管道中那樣,只能默認地接收。

·?消息隊列可以實現(xiàn)消息的隨機查詢,消息不一定要以先進先出的順序接收,也可以按消息的類型接收。

消息隊列的實現(xiàn)包括創(chuàng)建或打開消息隊列、發(fā)送消息、接收消息和控制消息隊列這 4 種操作。其中創(chuàng)建或打開消息隊列使用的函數(shù)是 msgget(),這里創(chuàng)建的消息隊列的數(shù)量會受到系統(tǒng)可支持的消息隊列數(shù)量的限制;發(fā)送消息使用的函數(shù)是 msgsnd()函數(shù),它把消息發(fā)送到已打開的消息隊列末尾;接收消息使用的函數(shù)是msgrcv(),它把消息從消息隊列中取走,與 FIFO 不同的是,這里可以指定取走某一條消息;最后控制消息隊列使用的函數(shù)是 msgctl(),它可以完成多項功能。

想要使用消息隊列還需要包含以下頭文件:

#include

#include

#include

創(chuàng)建或獲取消息隊列ID

msgget()函數(shù)

int msgget(key_t key, int msgflg);

該函數(shù)的作用是得到消息隊列標識符或創(chuàng)建一個消息隊列對象并返回消息隊列標識符:成功返回隊列ID,失敗返回-1。在以下兩種情況下,msgget()函數(shù)將創(chuàng)建一個新的消息隊列:

1.?如果沒有與鍵值key相對應的消息隊列,并且flag中包含了IPC_CREAT標志位。

2.?key參數(shù)為IPC_PRIVATE。

·?key:消息隊列的關鍵字值,多個進程可以通過它訪問同一個消息隊列,其中有個特殊值 IPC_PRIVATE,它用于創(chuàng)建當前進程的私有消息隊列。

·?msgflg表示創(chuàng)建的消息隊列的模式標志參數(shù),在真正使用時需要與IPC對象存取權限(如0600)進行“|”運算來確定消息隊列的存取權限。msgflg有多種情況:如果為0則表示取消息隊列標識符,若該消息隊列不存在則函數(shù)會報錯;如果是?IPC_CREAT?&?msgflg?為真則表示:如果內核中不存在關鍵字與key相等的消息隊列,則新建一個消息隊列;如果存在這樣的消息隊列,返回此消息隊列的標識符,而如果為?IPC_CREAT?|?IPC_EXCL?為真則表示:如果內核中不存在鍵值與key相等的消息隊列,則新建一個消息隊列;如果存在這樣的消息隊列則報錯,這些參數(shù)是可以通過“|”運算符聯(lián)合起來的,因為它始終是int類型的參數(shù)。

該函數(shù)可能返回以下錯誤代碼:

·?EACCES:指定的消息隊列已存在,但調用進程沒有權限訪問它

·?EEXIST:key指定的消息隊列已存在,而msgflg中同時指定IPC_CREAT和IPC_EXCL標志

·?ENOENT:key指定的消息隊列不存在同時msgflg中沒有指定IPC_CREAT標志

·?ENOMEM:需要建立消息隊列,但內存不足

·?ENOSPC:需要建立消息隊列,但已達到系統(tǒng)的限制

使用該函數(shù)需要注意的以下幾點:

1.?選項 msgflg 是一個位屏蔽字,因此 IPC_CREAT、IPC_EXCL 和權限 mode 可以用位或的方式疊加起來,比如:?msgget(key,?IPC_CREAT?|?0666);?表示如果 key 對應的消息隊列不存在就創(chuàng)建,且權限指定為 0666,若已存在則直接獲取消息隊列ID。

2.?權限只有讀和寫,執(zhí)行權限是無效的,例如 0777 跟 0666 是等價的。

3.?當 key 被指定為 IPC_PRIVATE 時,系統(tǒng)會自動產(chǎn)生一個未用的 key 來對應一個新的消息隊列對象,這個消息隊列一般用于進程內部間的通信。

發(fā)送消息與接收消息

msgsnd()函數(shù)

這個函數(shù)的主要作用就是將消息寫入到消息隊列,俗稱發(fā)送一個消息。

函數(shù)原型:

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

函數(shù)傳入值:

msqid:消息隊列標識符。

msgp:發(fā)送給隊列的消息。msgp可以是任何類型的結構體,但第一個字段必須為long類型,即表明此發(fā)送消息的類型,msgrcv()函數(shù)則根據(jù)此接收消息。msgp定義的參照格式如下:

/*msgp定義的參照格式*/

struct s_msg{

????long type; ?/* 必須大于0,消息類型 */

char mtext[1]; ?/* 消息正文,可以是其他任何類型 */

} msgp;

msgsz:要發(fā)送消息的大小,不包含消息類型占用的4個字節(jié),即mtext的長度。

msgflg:如果為0則表示:當消息隊列滿時,msgsnd()函數(shù)將會阻塞,直到消息能寫進消息隊列;如果為IPC_NOWAIT則表示:當消息隊列已滿的時候,msgsnd()函數(shù)不等待立即返回;如果為IPC_NOERROR:若發(fā)送的消息大于size字節(jié),則把該消息截斷,截斷部分將被丟棄,且不通知發(fā)送進程。

如果成功則返回0,如果失敗則返回-1,并且錯誤原因存于error中。

錯誤代碼:

·?EAGAIN:參數(shù)msgflg設為IPC_NOWAIT,而消息隊列已滿。

·?EIDRM:標識符為msqid的消息隊列已被刪除。

·?EACCESS:無權限寫入消息隊列。

·?EFAULT:參數(shù)msgp指向無效的內存地址。

·?EINTR:隊列已滿而處于等待情況下被信號中斷。

·?EINVAL:無效的參數(shù)msqid、msgsz或參數(shù)消息類型type小于0。

msgsnd()為阻塞函數(shù),當消息隊列容量滿或消息個數(shù)滿會阻塞。消息隊列已被刪除,則返回EIDRM錯誤;被信號中斷返回E_INTR錯誤。

如果設置IPC_NOWAIT消息隊列滿或個數(shù)滿時會返回-1,并且置EAGAIN錯誤。

msgsnd()解除阻塞的條件有以下三個條件:

1.?消息隊列中有容納該消息的空間。

2.?msqid代表的消息隊列被刪除。

3.?調用msgsnd函數(shù)的進程被信號中斷。

msgrcv()函數(shù)

函數(shù)原型:

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

msgrcv()函數(shù)是從標識符為msqid的消息隊列讀取消息并將消息存儲到msgp中,讀取后把此消息從消息隊列中刪除,也就是俗話說的接收消息。

函數(shù)傳入值:

·?msqid:消息隊列標識符。

·?msgp:存放消息的結構體,結構體類型要與msgsnd()函數(shù)發(fā)送的類型相同。

·?msgsz:要接收消息的大小,不包含消息類型占用的4個字節(jié)。

·?msgtyp有多個可選的值:如果為0則表示接收第一個消息,如果大于0則表示接收類型等于msgtyp的第一個消息,而如果小于0則表示接收類型等于或者小于msgtyp絕對值的第一個消息。

msgflg取值情況如下:

·?0: 阻塞式接收消息,沒有該類型的消息msgrcv函數(shù)一直阻塞等待

·?IPC_NOWAIT:若在消息隊列中并沒有相應類型的消息可以接收,則函數(shù)立即返回,此時錯誤碼為ENOMSG

·?IPC_EXCEPT:與msgtype配合使用返回隊列中第一個類型不為msgtype的消息

·?IPC_NOERROR:如果隊列中滿足條件的消息內容大于所請求的size字節(jié),則把該消息截斷,截斷部分將被丟棄

msgrcv()函數(shù)如果接收消息成功則返回實際讀取到的消息數(shù)據(jù)長度,否則返回-1,錯誤原因存于error中。

錯誤代碼

·?E2BIG:消息數(shù)據(jù)長度大于msgsz而msgflag沒有設置IPC_NOERROR

·?EIDRM:標識符為msqid的消息隊列已被刪除

·?EACCESS:無權限讀取該消息隊列

·?EFAULT:參數(shù)msgp指向無效的內存地址

·?ENOMSG:參數(shù)msgflg設為IPC_NOWAIT,而消息隊列中無消息可讀

·?EINTR:等待讀取隊列內的消息情況下被信號中斷

msgrcv()函數(shù)解除阻塞的條件也有三個:

1.?消息隊列中有了滿足條件的消息。

2.?msqid代表的消息隊列被刪除。

3.?調用msgrcv()函數(shù)的進程被信號中斷。

操作消息隊列

消息隊列是可以被用戶操作的,比如設置或者獲取消息隊列的相關屬性,那么可以通過msgctl()函數(shù)去處理它。

函數(shù)原型:

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

函數(shù)傳入值:

·?msqid:消息隊列標識符。

cmd的取值有多個:

·?IPC_STAT 獲取該 MSG 的信息,獲取到的信息會儲存在結構體 msqid_ds 類型的buf中。

·?IPC_SET 設置消息隊列的屬性,要設置的屬性需先存儲在結構體 msqid_ds類型的buf中,可設置的屬性包括:msg_perm.uid、msg_perm.gid、msg_perm.mode以及msg_qbytes,儲存在結構體 msqid_ds。

·?IPC_RMID 立即刪除該 MSG,并且喚醒所有阻塞在該 MSG 上的進程,同時忽略第三個參數(shù)。

·?IPC_INFO 獲得關于當前系統(tǒng)中 MSG 的限制值信息。

·?MSG_INFO 獲得關于當前系統(tǒng)中 MSG 的相關資源消耗信息。

·?MSG_STAT 同 IPC_STAT,但 msgid 為該消息隊列在內核中記錄所有消息隊列信息的數(shù)組的下標,因此通過迭代所有的下標可以獲得系統(tǒng)中所有消息隊列的相關信息。

·?buf:相關信息結構體緩沖區(qū)。

函數(shù)返回值:

·?成功:0

·?出錯:-1,錯誤原因存于error中

錯誤代碼:

·?EACCESS:參數(shù)cmd為IPC_STAT,卻無權限讀取該消息隊列。

·?EFAULT:參數(shù)buf指向無效的內存地址。

·?EIDRM:標識符為msqid的消息隊列已被刪除。

·?EINVAL:無效的參數(shù)cmd或msqid。

·?EPERM:參數(shù)cmd為IPC_SET或IPC_RMID,卻無足夠的權限執(zhí)行。

消息隊列實例

發(fā)送者:

l?獲取消息隊列的 ID

l?將數(shù)據(jù)放入一個附帶有標識的特殊的結構體,發(fā)送給消息隊列。

接收者:

l?獲取消息隊列的 ID

l?將指定標識的消息讀出。

l?當發(fā)送者和接收者都不再使用消息隊列時,及時刪除它以釋放系統(tǒng)資源。

發(fā)送函數(shù):

接收函數(shù)

第一個終端執(zhí)行 msgsnd 發(fā)送消息

第二個終端執(zhí)行 msgrcv 接收消息

Hankin

2020.08.17

總結

以上是生活随笔為你收集整理的jmstemplate 获取队列id_学习Linux(38)消息队列的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。