1、什麼是消息隊列?數據結構
消息隊列提供了一種從一個進程向另外一個進程發送一個數據塊的方法。 每一個數據塊都被認爲是有一個類型,接收者進程接收的數據塊能夠有不一樣的類型值。咱們能夠經過發送消息來避免命名管道的同步和阻塞問題。消息隊列與管道不一樣的是,消息隊列是基於消息的,而管道是基於字節流的,且消息隊列的讀取不必定是先入先出。消息隊列與命名管道有一樣的不足,就是每一個消息的最大長度是有上限的(MSGMAX),每一個消息隊列的總的字節數是有上限的( MSGMNB),系統上消息隊列的總數也有一個上限( MSGMNI)。
ide
2、函數函數
1.建立新消息隊列或取得已存在消息隊列原型: int msgget(key_t key, int msgflg);參數:
key:能夠認爲是一個端口號,也能夠由函數ftok生成。
msgflg:
IPC_CREAT 若是IPC不存在,則建立一個IPC資源,不然打開操做。
IPC_EXCL:只有在共享內存不存在的時候,新的共享內存才創建,不然就產生錯誤。若是單獨使用IPC_CREAT, XXXget()函數要麼返回一個已經存在的共享內存的操做符,要麼返回一個新建的共享內存的標識符。若是將IPC_CREAT和IPC_EXCL標誌一塊兒使用, XXXget()將返回一個新建的IPC標識符;若是該IPC資源已存在,或者返回-1。
IPC_EXEL標誌原本並無太大的意義,可是和IPC_CREAT標誌一塊兒使用能夠來保證所得的對象是新建的,而不是打開已有的對象。
2.向隊列讀/寫消息原型:
msgrcv從隊列中取出消息: ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, intmsgflg);
msgsnd將數據放到消息隊列中: int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);spa
參數:
msqid:消息隊列的標識碼
msgp:指向消息緩衝區的指針,此位置用來暫時存儲發送和接收的消息,是一個用戶可定義的通用結構,形態以下:
struct msgstru{
long mtype; //大於0
char mtext[用戶指定大小];
};
msgsz:消息的大小。
msgtyp:從消息隊列內讀取的消息形態。若是值爲零,則表名消息隊列中的全部消息都會被讀取。
msgflg:用來指明核心程序在隊列沒有數據的狀況下所應採起的行動。若是msgflg和常數IPC_NOWAIT合用,則在msgsnd()執行時如果消息隊列已滿,則msgsnd()將不會阻塞,會當即返回-1,若是執行的是msgrcv(),則在消息隊列呈空時,不作等待立刻返回-1,並設定錯誤碼爲ENOMSG。當msgflg爲0時, msgsnd()及msgrcv()在隊列呈滿或呈空的情形時,採起阻塞等待的處理模式。
3.設置消息隊列屬性原型: int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );參數: msgctl 系統調用對 msgqid 標識的消息隊列執行cmd 操做,系統定義了 3 種 cmd 操做: IPC_STAT , IPC_SET , IPC_RMID
IPC_STAT : 該命令行來獲取消息隊列對應的 msqid_ds 數據結構,並將其保存到 buf 指定的地址空間。
IPC_SET : 該命令用來設置消息隊列的屬性,要設置的屬性存儲在buf中。
IPC_RMID : 從內核中刪除 msqid 標識的消息隊列。
命令行
廢話很少說貼上代碼纔有說服性:指針
comm.h:
orm
#pragma onceserver
#include<stdio.h>對象
#include<sys/types.h>隊列
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
#include<errno.h>
#define _PROJ_NAME_ "/tmp"
#define _PROJ_ID_ 0X666
#define _SIZE_ 1024
#define _SEVER_TYPE_ 1
#define _CLIENT_TYPE_ 2
struct msgbuf{
long mtype;
char mtext[_SIZE_];
};
int create_msg_queue();//建立消息隊列
int get_msg_queue(); //獲得消息隊列
int destroy_msg_queue(int msg_id);//銷燬消息隊列
int recv_msg(int msg_id,int t, char*out);//接收消息
int send_msg(int msg_id,int t,const char*msg);//發送消息
comm.c:
#include"comm.h"
static int com_msg_queue(int flags)
{
key_t _key=ftok(_PROJ_NAME_,_PROJ_ID_);
if(_key<0)
{
perror("ftok");
return -1;
}
int msg_id=msgget(_key,flags);
if(msg_id<0)
{
perror("msgget");
}
return msg_id;
}
int create_msg_queue()
{
int flags=IPC_CREAT|IPC_EXCL|0644;
return com_msg_queue(flags);
}
int get_msg_queue()
{
int flags=IPC_CREAT;
return com_msg_queue(flags);
}
int destroy_msg_queue(int msg_id)
{
if(msgctl(msg_id,IPC_RMID,NULL)<0)
{
perror("msgctl");
return -1;
}
return 0;
}
int send_msg(int msg_id,int t,const char*msg)
{
struct msgbuf _msg;
_msg.mtype=t;
strncpy(_msg.mtext,msg,strlen(msg)+1);
if(msgsnd(msg_id,&_msg,sizeof(_msg.mtext),0)<0)
{
perror("msgsnd");
return -1;
}
return 0;
}
int recv_msg(int msg_id,int t,char*out)
{
struct msgbuf _msg;
_msg.mtype=t;
memset(_msg.mtext,'\0',sizeof(_msg.mtext));
if(msgrcv(msg_id,&_msg,sizeof(_msg.mtext),t,0)<0)
{
perror("msgrcv");
return -1;
}
else
{
strcpy(out,_msg.mtext);
}
return 0;
}
client.c:
#include"comm.h"
int main()
{
int msg_id=get_msg_queue();
char buf[_SIZE_];
while(1)
{
printf("please enter:");
fflush(stdout);
read(0,buf,sizeof(buf)-1);
send_msg(msg_id,_CLIENT_TYPE_,buf);
memset(buf,'\0',sizeof(buf));
recv_msg(msg_id,_SEVER_TYPE_,buf);
printf("sever->client:%s\n",buf);
}
return 0;
}
server.c:
#include"comm.h"
int main()
{
int msg_id=create_msg_queue();
char buf[_SIZE_];
while(1)
{
memset(buf,'\0',sizeof(buf));
sleep(20);
recv_msg(msg_id,_CLIENT_TYPE_,buf);
printf("client->sever:%s\n",buf);
printf("please enter:");
fflush(stdout);
read(0,buf,sizeof(buf)-1);
send_msg(msg_id,_SEVER_TYPE_,buf);
}
destroy_msg_queue(msg_id);
return 0;
}