十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專業(yè)推廣+無(wú)憂售后,網(wǎng)站問題一站解決
這篇文章主要講解了“Linux中消息隊(duì)列的使用方式”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Linux中消息隊(duì)列的使用方式”吧!
創(chuàng)新互聯(lián)建站主營(yíng)思明網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,重慶APP開發(fā),思明h5小程序制作搭建,思明網(wǎng)站營(yíng)銷推廣歡迎思明等地區(qū)企業(yè)咨詢
1 消息隊(duì)列的概念及使用過(guò)程
1)消息隊(duì)列的概念
消息隊(duì)列就是一個(gè)消息的鏈表。一條消息可以看作一個(gè)數(shù)據(jù)記錄,此數(shù)據(jù)具有特定的格式。
進(jìn)程可以按照特定的規(guī)則向隊(duì)列中添加(寫入)消息;其他的進(jìn)程則可以從消息隊(duì)列中讀走消息。
2)消息隊(duì)列的應(yīng)用場(chǎng)景
消息隊(duì)列本身就是IPC通信中的內(nèi)容,所以它主要用于進(jìn)程間的通信。
消息有讀寫,所以發(fā)送的消息可以用于動(dòng)作的通知信號(hào),也可以接收數(shù)據(jù)然后做其他處理。
2 消息隊(duì)列相關(guān)的結(jié)構(gòu)及函數(shù)
0)消息隊(duì)列相關(guān)的結(jié)構(gòu)
每個(gè)隊(duì)列都有一個(gè)msqid_ds結(jié)構(gòu)與其相關(guān)聯(lián),結(jié)構(gòu)如下。
struct msqid_ds { struct ipc_perm msg_perm; // 消息隊(duì)列的存取權(quán)限以及其他一些信息 time_t msg_stime; // 最近一次隊(duì)列接受消息的時(shí)間 time_t msg_rtime; // 最近一次從隊(duì)列中取出消息的時(shí)間 time_t msg_ctime; // 最近一次隊(duì)列發(fā)生改動(dòng)的時(shí)間 unsigned long __msg_cbytes; // 隊(duì)列中消息的占用內(nèi)存的字節(jié)數(shù) msgqnum_t msg_qnum; // 隊(duì)列中當(dāng)前的消息數(shù) msglen_t msg_qbytes; // 隊(duì)列所占用內(nèi)存的最大字節(jié)數(shù) pid_t msg_lspid; // 最近一次向隊(duì)列發(fā)送消息的進(jìn)程的pid msgsnd pid_t msg_lrpid; // 最近一次從隊(duì)列中取出消息的進(jìn)程的pid };
struct ipc_perm { key_t key; ushort uid; // 用戶id,有效的用戶ID和有效的組id(euid和egid) ushort gid; ushort cuid; // 創(chuàng)建者的euid和egid ushort cgid; ushort mode; // 訪問模式參見模式標(biāo)志 ushort seq; // IPC對(duì)象使用頻率信息 };
1)msgget函數(shù)
msgget函數(shù)用于創(chuàng)建或打開消息隊(duì)列。
① 函數(shù)原型。
int msgget(key_t key,int msgflg)
② 頭文件。
includeinclude include
③ 參數(shù)。
key:鍵值。
msgflg:打開標(biāo)志。IPC_CREAT:表明新創(chuàng)建的一個(gè)消息隊(duì)列。
④ 返回值。
成功:返回消息隊(duì)列的id。
失?。?1。
2)msgsnd函數(shù)
msgsnd函數(shù)用于發(fā)送消息,即寫消息到消息隊(duì)列。
① 函數(shù)原型。
int msgsnd(int msgid,const void *msgp,size_t msgsz,int msgflg)
② 頭文件。
includeinclude include
③ 參數(shù)。
msgid:消息隊(duì)列的id。
msgp:指向要發(fā)送的消息。
msgsz:消息的長(zhǎng)度。
msgflg:標(biāo)志位。
④ 返回值。
成功:0。
失?。?1。
3)msgrcv函數(shù)
msgrcv函數(shù)用于讀消息隊(duì)列,即從消息隊(duì)列接收消息。
① 函數(shù)原型。
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg) ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,intmsgflg)
② 頭文件。
#include#include #include
③ 參數(shù)。
msqid:消息隊(duì)列的id。
msgp:存放消息。
msgsz:希望取到的消息的最大長(zhǎng)度。
msgtyp:消息的類型,分下面三種情況:
當(dāng) msgtyp = 0:忽略類型,直接取隊(duì)列中的第一條消息。
當(dāng) msgtyp > 0: 取消息隊(duì)列中類型等于msgtyp的第一條消息。
當(dāng) msgtyp < 0: 取類型比msgtyp的絕對(duì)值要小或等于的消息,如果有多條消息
滿足該條件,取類型最小的一條。
④ 返回值。
成功:實(shí)際接收到的消息的數(shù)據(jù)長(zhǎng)度。
失?。?1。
4)msgctl函數(shù)
msgctl函數(shù)用于操作消息隊(duì)列,比如進(jìn)行消息隊(duì)列的刪除等等。
① 函數(shù)原型。
int msgctl(int msqid,int cmd,struct msqid_ds *buf)
② 頭文件。
#include#include #include
③ 參數(shù)。
msqid:消息隊(duì)列的id。
cmd:消息隊(duì)列的操作命令,此參數(shù)指定對(duì)msqid指定的隊(duì)列要執(zhí)行的命令。
IPC_STAT:取此隊(duì)列的msqidds結(jié)構(gòu),并將它存放在buf指向的結(jié)構(gòu)中。
IPCSET:將字段msg_perm.uid、msg_perm.gid、msg_perm.mode和msg_qbytes從buf指向的結(jié)構(gòu)復(fù)制到與這個(gè)隊(duì)列相關(guān)的msqid_ds結(jié)構(gòu)中。
此命令只能由下列兩種進(jìn)程執(zhí)行:
一種是其有效用戶ID等于msg_perm.cuid或msg perm.uid。
另一種是具有超級(jí)用戶特權(quán)的進(jìn)程。只有超級(jí)用戶才能增加msg_qbytes的值。
IPC_RMID:從系統(tǒng)中刪除該消息隊(duì)列以及仍在該隊(duì)列中的所有數(shù)據(jù)。這種刪除立即生效。
仍在使用這一消息隊(duì)列的其他進(jìn)程在它們下一次試圖對(duì)此隊(duì)列進(jìn)行操作時(shí),將得到EIDRM錯(cuò)誤。
此命令只能由下列兩種進(jìn)程執(zhí)行:
一種是其有效用戶ID等于msg_perm.cuid或msg_perm.uid。
另一種是具有超級(jí)用戶特權(quán)的進(jìn)程。這3條命令(IPC_STAT、IPC_SET和IPC_RMID)也可用于信號(hào)量和共享存儲(chǔ)。
buf:獲取內(nèi)核中的msqid_ds結(jié)構(gòu),通常不用。
④ 返回值。
成功:0。
失?。?1。
3 實(shí)例代碼
下面用兩個(gè)進(jìn)程,給大家演示下消息隊(duì)列的使用過(guò)程。
實(shí)例代碼如下,說(shuō)明都在代碼注釋中了,圖片。
SendQueue.c。
#include#include #include #include #include // 消息結(jié)構(gòu)體 struct msg { long msgtype; //消息的類型 char msgtext[1024]; //消息的長(zhǎng)度 }; void main(int argc, char *argv[]) { int msgid; char str[256]; struct msg msgst; key_t key = ftok("/tmp",600); //創(chuàng)建消息隊(duì)列 msgid = msgget(key,0666 | IPC_CREAT); //鍵盤輸入消息 while(1) { //獲取消息數(shù)據(jù) printf("\nPlease enter a message to send,input 'end' to quit!\n\n"); scanf("%s",str); strcpy(msgst.msgtext,str); if(strncmp(str, "end", 3) == 0) { printf("\n"); break; } //發(fā)送消息 msgsnd(msgid,&msgst,sizeof(struct msg),0); } //輸出消息隊(duì)列 msgctl(msgid,IPC_RMID,0); }
ReceiveQueue.c。
#include#include #include #include #include #include // 消息結(jié)構(gòu)體 struct msg { long msgtype; char msgtext[1024]; }; int main(int argc, char *argv[]) { int RunFlag = 1; // 循環(huán)標(biāo)志 int msgid = -1; // 消息id long msgtp = 0; // 消息類型 struct msg msgst; // 消息結(jié)構(gòu)體變量 key_t key = ftok("/tmp",600); // 創(chuàng)建一個(gè)鍵值 msgid = msgget(key, 0666 | IPC_CREAT); //建立消息隊(duì)列 if(msgid == -1) { exit(1); // 異常退出 } while(RunFlag) // 從隊(duì)列中獲取消息,直到遇到end消息為止 { if(msgrcv(msgid,&msgst,sizeof(struct msg), msgtp, 0) == -1) { exit(1); // 異常退出 } printf("\nThe message received is: %s\n\n",msgst.msgtext); if(strncmp(msgst.msgtext, "end", 3) == 0) // 遇到end結(jié)束 { RunFlag = 0; // 置退出循環(huán)標(biāo)志 } } if(msgctl(msgid, IPC_RMID, 0) == -1) // 刪除消息隊(duì)列 { exit(1); // 異常退出 } exit(0); // 正常退出 }
編譯程序,先運(yùn)行接收程序,再運(yùn)行發(fā)送程序,輸入要發(fā)送的消息,退出輸入end。
① 兩個(gè)終端運(yùn)行結(jié)果如下:
② 單個(gè)終端運(yùn)行結(jié)果如下:
感謝各位的閱讀,以上就是“Linux中消息隊(duì)列的使用方式”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Linux中消息隊(duì)列的使用方式這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!