Linux訊息佇列---程序之間通訊
技術標籤:linux系統程式設計學習
Linux訊息佇列—程序間通訊
訊息佇列
- 訊息佇列也是在記憶體中開闢的區域,有一定的大小限制
- 訊息佇列的通訊是將訊息打包放入訊息佇列中,其他程序可以從訊息佇列中提取訊息
- 當訊息佇列滿的時候傳送訊息函式可能阻塞(設定:0)
- 訊息結構中第一個必須是long型別,作為訊息型別(具體賦值自己定義)
- 訊息結構體中除了第一個long型別的資料,其他的都是訊息正文
- 訊息佇列建立後也不會隨程序銷燬,需要手動刪除
- 訊息佇列中一次只能傳送或接收1條訊息
- 如果想正確接收訊息,那麼傳送和接收訊息的結構體要一致
- 在訊息接收的時候並不是嚴格的先進先出,可以指明接受的訊息型別
int msgget(key_t key, int flag);
標頭檔案:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
功能 : 建立或開啟一個訊息佇列
引數 : key
flag :開啟訊息佇列的許可權
IPC_CREAT : 建立一個ipc物件
IPC_EXCL : 如果這個物件已經存在則返回errno = EEXIST
mode: 建立許可權
返回值 : 成功 返回一個訊息佇列id 失敗 -1
int msgsnd(int msqid, const void *msgp, size_t size, int flag); ----》 傳送訊息的時候記得要指明訊息型別
標頭檔案:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
功能: 向訊息佇列中存入訊息
引數: msgid
msgp : 指向要傳送的訊息
struct msgbuf{
long msgtype; //表明訊息的型別
char buf[64]; //訊息內容
};
size : 傳送訊息的正文大小 sizeof(struct msgbuf) - sizeof(long)
flag : IPC_NOWAIT 訊息沒有傳送完成函式也會立即返回。
0:直到傳送完成函式才返回
返回值 成功 返回0 失敗 -1
int msgrcv(int msgid, void* msgp, size_t size, long msgtype, int flag);
標頭檔案:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
功能 : 從訊息佇列中獲取一個訊息
引數 : msgid
msgp : 指向訊息結構體
size ; 接收的結構體正文大小 sizeof(struct msgbuf) - sizeof(long)
msgtype : 0:接收訊息佇列中第一個訊息。
大於0:接收訊息佇列中第一個型別為msgtyp的訊息.
小於0:接收訊息佇列中型別值不小於 msgtyp的絕對值 且型別值又最小的訊息。
flag : 0:若無訊息函式會一直阻塞
IPC_NOWAIT:若沒有訊息,程序會立即返回ENOMSG。
返回值 0 -1
int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );
標頭檔案:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
功能 : 控制訊息佇列
引數 : msgid
cmd : 命令 (參照共享記憶體)
IPC_STAT:讀取訊息佇列的屬性,並將其儲存在buf指向的緩衝區中。
IPC_SET:設定訊息佇列的屬性。這個值取自buf引數。
IPC_RMID:從系統中刪除訊息佇列。
buf : 訊息佇列屬性結構體
返回值 成功:0 失敗:-1
檢視和刪除訊息佇列的命令:
ipcs -q //檢視訊息佇列的狀態
ipcrm -q id //刪除一個訊息佇列
下面就看看具體的例子:
檢視訊息佇列:
現在系統裡面不存在建立的訊息佇列,下面編寫兩個demon程式:
//msgqueuerecv.c
#include<stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <unistd.h>
#define ERROR -1
#define OK 0
#define MSGSIZE 128
typedef struct msgbuf{
long msgtype; //表明訊息的型別
char buf[MSGSIZE]; //訊息內容
}S_MSGBUF;
int main(void){
char *pkey="aaron"; //指定key值
key_t key = *(int *)pkey;
int msgid;
S_MSGBUF sbuf;
msgid=msgget(key,IPC_CREAT|0666); //建立訊息佇列ID
if(ERROR==msgid){
printf("msgget error\n");
return ERROR;
}
while(1){
memset(&sbuf,0,sizeof(sbuf));
sbuf.msgtype=1;
msgrcv(msgid,&sbuf,MSGSIZE,sbuf.msgtype,0); //接收訊息
if(strncmp(sbuf.buf,"quit",4)==OK){
break;
}else{
printf("%s\n",sbuf.buf);
}
// sleep(1);
}
int ret=msgctl(msgid,IPC_RMID,NULL); //刪除訊息佇列
if(ret==ERROR){
printf("msgctl delete fail\n");
}else{
printf("bye bye\n");
}
return OK;
}
//msgqueuesend.c
#include<stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <unistd.h>
#define ERROR -1
#define OK 0
#define MSGSIZE 128
typedef struct msgbuf{
long msgtype; //表明訊息的型別
char buf[MSGSIZE]; //訊息內容
}S_MSGBUF;
int main(void){
char *pkey="aaron"; //指定key值
key_t key = *(int *)pkey;
int msgid;
S_MSGBUF sbuf;
msgid=msgget(key,IPC_CREAT|0666); //建立訊息佇列ID
if(ERROR==msgid){
printf("msgget error\n");
return ERROR;
}
while(1){
memset(&sbuf,0,sizeof(sbuf));
fgets(sbuf.buf,MSGSIZE,stdin);
sbuf.msgtype=1;
msgsnd(msgid,&sbuf,MSGSIZE,IPC_NOWAIT); //傳送訊息
if(strncmp(sbuf.buf,"quit",4)==OK){
break;
}
sleep(1);
}
return OK;
}
編譯兩個程式:
執行msgqueuesend程式,然後檢視是否有新的訊息佇列建立:
有一個擁有者是book的訊息佇列被建立了,現在訊息佇列中的訊息數為0,我們寫幾個訊息看看是什麼效果
發現訊息佇列中的數字有了變化,我們分別寫了三條訊息,然後呢,訊息的位置顯示是3,我們建立的每個訊息佇列的大小為128位元組,然後3個就是384位元組。
那接下來,我們讀取佇列中的訊息,看看結果是什麼樣子:
訊息已經被讀出來了,並且列印了出來,然後再看看訊息佇列的數字,已經變為0了,以上就是兩個獨立的程序通過訊息佇列的方式,進行簡單的訊息互動傳遞。