消息隊列特性
- 消息隊列存在于Linux核心中,可以使資料雙向流動
- 資料在核心中,即使程序結束資料依然存在
- 消息隊列實際上是消息連結清單,每個隊列都有自己的辨別符
消息隊列API
- msgget——建立一個消息隊列
- msgsnd、msgrcv——添加資料到消息隊列、從消息隊列擷取資料
- msgctl——控制消息隊列
一、msgget——建立一個消息隊列
1.原函數
表頭檔案
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
定義函數
int msgget(key_t key, int msgflg);
函數說明——建立和通路一個消息隊列
key——消息隊列的名稱(使用ftok()函數擷取)
msgflg——消息隊列的通路權限
傳回值——成功傳回此消息隊列的辨別符(非零整數)。失敗時傳回-1,失敗原因在errno中
2.示例
key_t key;
key = ftok(".",'z');
int msgId = msgget(key,IPC_CREAT|0777);//建立和通路一個消息隊列
二、msgsnd、msgrcv——添加資料到消息隊列、從消息隊列擷取資料
1.原函數
表頭檔案
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
定義函數
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
函數說明——msgsnd()添加資料到消息隊列、msgrcv()從消息隊列擷取資料
msqid —— 由msgget()傳回的隊列辨別符
msgp —— 需要存放/讀取的結構體
msgsz —— 需要存放/讀取的大小
msgtyp —— 讀取消息隊列的位置
msgflg —— 預設值為0
傳回值——成功msgsnd()傳回0,msgrcv()傳回實際複制到mtext數組中的位元組數。錯誤兩個函數都傳回-1,errno表示錯誤
2.參數取值
msgp預設結構體如下:
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
3.示例
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[128]; /* message data */
};
struct msgbuf sendBuf = {988,"thank your welcome\n"};
struct msgbuf readBuf;
msgrcv(msgId,&readBuf,sizeof(readBuf.mtext),888,0);//從消息隊列擷取資料
msgsnd(msgId,&sendBuf,strlen(sendBuf.mtext),0);//添加資料到消息隊列
三、msgctl——控制消息隊列
1.原函數
表頭檔案
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
定義函數
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
函數說明—— 控制消息隊列,它與共享記憶體的shmctl函數相似
msqid —— 由msgget()傳回的隊列辨別符
cmd —— 控制msqid_ds結構體指令
buf —— 記錄消息隊列的資訊(消息隊列模式和通路權限)(預設為NULL)
傳回值——成功時傳回0。失敗時傳回-1,errno表示錯誤
2.參數取值
command是将要采取的動作,它可以取3個值,
IPC_STAT:把msgid_ds結構中的資料設定為消息隊列的目前關聯值,即用消息隊列的目前關聯值覆寫msgid_ds的值。
IPC_SET:如果程序有足夠的權限,就把消息列隊的目前關聯值設定為msgid_ds結構中給出的值
IPC_RMID:删除消息隊列
msqid_ds預設結構體如下:
struct msqid_ds {
struct ipc_perm msg_perm; /* Ownership and permissions */
time_t msg_stime; /* Time of last msgsnd(2) */
time_t msg_rtime; /* Time of last msgrcv(2) */
time_t msg_ctime; /* Time of last change */
unsigned long __msg_cbytes; /* Current number of bytes in
queue (nonstandard) */
msgqnum_t msg_qnum; /* Current number of messages
in queue */
msglen_t msg_qbytes; /* Maximum number of bytes
allowed in queue */
pid_t msg_lspid; /* PID of last msgsnd(2) */
pid_t msg_lrpid; /* PID of last msgrcv(2) */
};
3.示例
消息隊列通信例程
程式1
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct msgbuf
{
long mtype; /* message type, must be > 0 */
char mtext[50]; /* message data */
};
int main()
{
struct msgbuf sndbuf={889,"Hello"};
struct msgbuf rcvbuf;
key_t key;
int msgid;
key=ftok(".",'k');//鍵值擷取
msgid=msgget(key,IPC_CREAT|0777);//建立一個消息隊列
msgsnd(msgid,&sndbuf,sizeof(sndbuf.mtext),0);//添加資料到消息隊列
msgrcv(msgid,&rcvbuf,sizeof(rcvbuf.mtext),888,0);//從消息隊列擷取資料
printf("rcvbuf.mtype=%ld,rcvbuf.mtext=%s\n",rcvbuf.mtype,rcvbuf.mtext);
msgctl(msgid,IPC_RMID,NULL);//删除消息隊列
return 0;
}
程式2
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct msgbuf
{
long mtype; /* message type, must be > 0 */
char mtext[50]; /* message data */
};
int main()
{
struct msgbuf sndbuf={888,"World"};
struct msgbuf rcvbuf;
key_t key;
int msgid;
key=ftok(".",'k');//鍵值擷取
msgid=msgget(key,IPC_CREAT|0777);//通路一個消息隊列
msgrcv(msgid,&rcvbuf,sizeof(rcvbuf.mtext),889,0);//從消息隊列擷取資料
printf("rcvbuf.mtype=%ld,rcvbuf.mtext=%s\n",rcvbuf.mtype,rcvbuf.mtext);
msgsnd(msgid,&sndbuf,sizeof(sndbuf.mtext),0);//添加資料到消息隊列
msgctl(msgid,IPC_RMID,NULL);//删除消息隊列
return 0;
}
運作結果:打開任意程式後消息隊列阻塞,等待另外一個程式将所需資料錄入,開啟另外一程式後兩程式達到消息通信的目的。
rcvbuf.mtype=889,rcvbuf.mtext=Hello
rcvbuf.mtype=888,rcvbuf.mtext=World
星辰~念