一 what
消息隊列也是程序間通信的一種通信方式,在核心中建立一個消息隊列對象,不同的程序中,通過msgid來通路這個消息隊列實作程序間通信
|---| |---|
| A | | B |
|---| |---|
------------------------------------
|-------------|
| | 消息隊列
|-------------|
-------------------------------------
之前在介紹管道的時候,管道也是一個隊列,它是一個順序隊列,那麼這個隊列和消息隊列有什麼差別呢?
消息隊列是一個鍊式隊列
相關函數
1. 建立或者打開消息隊列的函數 msgget
所需頭檔案:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
原型: int msgget(key_t key, int flag)
參數: key 和消息隊列關聯的key值
flag 消息隊列的通路權限
傳回值: 成功,消息隊列ID,出錯 -1
2. 關閉: msgctl
原型: int msgctl(int msgqid, int cmd, struct msqid_ds *buf)
參數: msgqid 消息隊列ID
cmd IPC_STAT 讀取消息隊列的屬性,并将其儲存在buf指向的緩沖區中
IPC_SET 設定消息隊列的屬性,這個值取自buf參數
IPC_RMID 從系統中删除消息隊列
buf 消息緩沖區
傳回值: 成功 0,出錯 -1
3. 發送: msgsnd
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
原型: int msgsnd(int msgqid, const void *msgp, size_t size, int flag)
參數: msgqid 消息隊列ID
msgp 指向消息的指針,常用消息結構msgbuf如下
struct msgbuf {
long mtype; //消息類型
char mtext[N]; //消息正文
};
size 消息正文的位元組數
flag IPC_NOWAIT 消息沒有發送完成也會立即傳回
0: 直到發送完成函數才會傳回
傳回值: 成功 0,出錯 -1
4. 讀取: msgrcv
原型: int msgrcv(int msgqid, void *msgp, size_t size, long msgtype, int flag)
參數: msgqid 消息隊列ID
msgp 接收消息的緩沖區
size 要接收消息的位元組數
msgtype 0 接收消息隊列中第一個消息
大于0 接收消息隊列中第一個類型為msgtype的消息
小于0 接收消息隊列中類型值不大于msgtype的絕對值且類型值又最小的消息
flag IPC_NOWAIT 沒有消息,會立即傳回
0: 若無消息則會一直阻塞
傳回值: 成功 接收消息的長度,出錯 -1
二 how
- 建立消息隊列
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
#include "sys/types.h"
#include <sys/msg.h>
#include "signal.h"
#include "string.h"
int main(int argc, char *argv[])
{
int msgid;
msgid = msgget(IPC_PRIVATE, 0777);
if (msgid < 0) {
printf("create msg queue fail\n");
return -1;
}
printf("create msg queue sucess, msgid = %d\n", msgid);
system("ipcs -q");
return 0;
}
-
利用消息隊列實作程序間通信
發送函數
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
#include "sys/types.h"
#include <sys/msg.h>
#include "signal.h"
#include "string.h"
struct msgbuf {
long type; //消息類型
char voltage[124]; //消息正文
char ID[4];
};
int main(int argc, char *argv[])
{
int msgid, readret, key;
struct msgbuf sendbuf;
key = ftok("./a.c", 'a');
if (key < 0){
printf("create key fail\n");
return -1;
}
msgid = msgget(key, IPC_CREAT|0777);
if (msgid < 0) {
printf("create msg queue fail\n");
return -1;
}
printf("create msg queue sucess, msgid = %d\n", msgid);
system("ipcs -q");
// write message queue
sendbuf.type = 100;
while(1) {
memset(sendbuf.voltage, 0, 124); //clear send buffer
printf("please input message:\n");
fgets(sendbuf.voltage, 124, stdin);
//start write msg to msg queue
msgsnd(msgid, (void *)&sendbuf, strlen(sendbuf.voltage), 0);
}
return 0;
}
接收函數
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
#include "sys/types.h"
#include <sys/msg.h>
#include "signal.h"
#include "string.h"
struct msgbuf {
long type; //消息類型
char voltage[124]; //消息正文
char ID[4];
};
int main(int argc, char *argv[])
{
int msgid, key;
struct msgbuf readbuf;
key = ftok("./a.c", 'a');
if (key < 0){
printf("create key fail\n");
return -1;
}
msgid = msgget(key, IPC_CREAT|0777);
if (msgid < 0) {
printf("create msg queue fail\n");
return -1;
}
printf("create msg queue sucess, msgid = %d\n", msgid);
system("ipcs -q");
// read message queue
while(1) {
memset(readbuf.voltage, 0, 124); //clear recv buffer
//start read msg to msg queue
msgrcv(msgid, (void *)&readbuf, 124, 100, 0);
printf("recv data from message queue:%s", readbuf.voltage);
}
return 0;
}