Linux进程间通信(IPC)-------消息队列
消息隊列是進程間通信的一種方法,他有兩個操作,一個進程來發送消息(也就是向內存中寫入數據),另一個是獲取消息(也就是另外一個進程在內存中讀取數據)
下面來看消息隊列的
創建,寫入,讀取等需要用到的函數
創建:msgget((key_t) key,int msgflg)? ? ? ? ? 其中(key_t)key的話,我在管道,共享內存中都寫過,key值沒什么要求,大于零的32位整數就行,并且它是用來區分和別的消息隊列的,所以key值別和其他消息隊列重復就行
msgflg是個標志位,一般取IPC_CREAT :
如果消息隊列對象不存在,則創建之,否則則進行打開操作;下面附上幫助手冊
寫入數據(發送消息):int msgsnd ( int msqid, struct msgbuf *msgp, int msgsz, int msgflg )
其中參數msqid就是上述創建的消息隊列的id? ?
struct msgbuf *msgp這玩意就是結構體指針? 該結構體就是消息體
msgsz就是消息體的大小
msgflg一般默認為0
讀取數據(讀取消息):size_t msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long type,int msgflg)
smqid就是創建的消息隊列id??
struct msgbuf *msgp? 結構體指針
size_t msgsz 就是存消息的大小
long type? 就是消息的類型
int msgflg標志位,一般默認0
下面附上幫助手冊:
上述那個結構體struct msgbuf就是消息體,type用來區分消息,你發送或者獲取消息的類型,其類型必須是long
下面的char 的數組就是發送或者獲取消息的最大內存(這里有一點要提一下,就是上面說到msgsnd中消息體大小,只算這個結構體中的char數組,龍不計算在內)
?下面來進行代碼實現:發送端的編寫
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/msg.h>struct message
{long type;char buff[32];
};int main()
{int msgid = msgget((key_t)1234,IPC_CREAT|0600);//0600是權限assert(msgid != -1);struct message me;me.type = 1; //這塊將消息類型定義為1strcpy(me.buff,"hello"); //向buff中寫入hellomsgsnd(msgid,(void*)&me,32,0); //向消息隊列發送消息}
對獲取端的編寫:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/msg.h>struct message
{long type;char buff[32];
};int main()
{int msgid = msgget((key_t)1234,IPC_CREAT|0600);//0600是權限assert(msgid != -1);struct message me;msgrcv(msgid,&me,32,1,0); //消息存儲最多32 1是type類型 0是默認標志位printf("read msg:%s \n",me.buff);}
下面附上運行截圖(其中xiaoxi是發送消息,haha是獲取消息)? 那個已用字節數應該是32? ?因為xiaoxi這個發送端? 我剛剛運行了下 ,所以疊加起來就是64
?然后ipcs -q是查看消息隊列的使用情況的,鍵下面的4d2就是1234轉換為16進制的值
然后我們將發送消息的消息的類型值由1改為2,獲取端代碼不變,我們再來看一下結果
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/msg.h>struct message
{long type;char buff[32];
};int main()
{int msgid = msgget((key_t)1234,IPC_CREAT|0600);//0600是權限assert(msgid != -1);struct message me;me.type = 2; //這塊將消息類型定義為1strcpy(me.buff,"hello"); //向buff中寫入hellomsgsnd(msgid,(void*)&me,32,0); //向消息隊列發送消息}
然后我們就會發現,獲取端獲取不了數據,一直在那塊阻塞,因為類型不對,寫入端寫的是2類型,讀取的是1類型
?因為類型不對,寫入端寫的是2類型,讀取的是1類型,所以肯定是讀取不了的,那么有沒有什么辦法讓它可以讀取呢,最笨的辦法就是將讀取端的消息類型改為2,這也是最常規的辦法,下面我來弄一個很有意思的方法:
? ? ? ? 將讀取端msgrcv的消息類型改為0,也就是默認類型,這樣的話,它就會接受所有的數據類型,下面我們來試一下:只改獲取端,發送端代碼不該,還是2類型
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/msg.h>struct message
{long type;char buff[32];
};int main()
{int msgid = msgget((key_t)1234,IPC_CREAT|0600);//0600是權限assert(msgid != -1);struct message me;msgrcv(msgid,&me,32,0,0); //消息存儲最多32 1是type類型 0是默認標志位printf("read msg:%s \n",me.buff);}
附上運行截圖:
?然后刪除消息隊列msgctl(msgid,IPC_RMID,NULL)
將該代碼寫到獲取端的末尾就好!
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/msg.h>struct message
{long type;char buff[32];
};int main()
{int msgid = msgget((key_t)1234,IPC_CREAT|0600);//0600是權限assert(msgid != -1);struct message me;msgrcv(msgid,&me,32,0,0); //消息存儲最多32 1是type類型 0是默認標志位printf("read msg:%s \n",me.buff);if(msgctl(msgid,IPC_RMID,NULL) == -1) //這塊msgctl中的那個NULL參數還沒搞明白 下次課過去問一下老師在評論區補一下{printf("delete error");}}
這樣執行下來就可以在程序執行完成之后,刪除消息隊列!
“加油呀? 兄弟們? BAT? 我來了”
總結
以上是生活随笔為你收集整理的Linux进程间通信(IPC)-------消息队列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 求一个女人独立的个性签名。
- 下一篇: Linux多线程的进阶理解