您好,登錄后才能下訂單哦!
、什么是消息隊列
消息隊列提供了一種從一個進程向另一個進程發送一個數據塊的方法。 每個數據塊都被認為是有一個類型,接收者進程接收的數據塊可以有不同的類型值。我們可以通過發送消息來避免命名管道的同步和阻塞問題。消息隊列與管道不同的是,消息隊列是基于消息的,而管道是基于字節流的,且消息隊列的讀取不一定是先入先出。消息隊列與命名管道有一樣的不足,就是每個消息的最大長度是有上限的(MSGMAX),每個消息隊列的總的字節數是有上限的(MSGMNB),系統上消息隊列的總數也有一個上限(MSGMNI)。
注:消息隊列、共享內存和信號量都有一個共同的數據結構。
二、函數
1、創建消息隊列或取得已存在的消息隊列
int msgget(key_t key, int msgflg);
參數:
key:可以認為是一個端口號,也可以由函數ftok生成。
msgflg:
(1)IPC_CREAT 如果IPC不存在,則創建一個IPC資源,否則打開操作。
(2)IPC_EXCL:只有在共享內存不存在的時候,新的共享內存才建立,否則就產生錯誤。
如果單獨使IPC_CREAT,XXXget()函數要么返回一個已經存在的共享內存的操作符,要么返回一個新建的共享內存的標識符。
(3)如果將IPC_CREAT和IPC_EXCL標志一起使用,XXXget()將返回一個新建的IPC標識符;如果該IPC資源已存在,或者返回-1。
IPC_EXEL標志本身并沒有太大的意義,但是和IPC_CREAT標志一起使用可以用來保證
所得的對象是新建的,而不是打開已有的對象。
2.向隊列讀/寫消息
從消息隊列中取消息
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
將數據放到消息隊列中
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
參數:
msqid:消息隊列的標識碼
msgp:指向消息緩沖區的指針,此位置用來暫存發送和接受的消息,是一個用戶可定義的數據結構。
struct msgstru{ long mtype; //大于0 char mtext[用戶指定大小]; };
msgsz:消息的大小
msgtype:從消息隊列內讀取消息的形態,如果值為零,表示消息隊列中所有值都會被讀取。
msgflg:用來指明核心程序在隊列沒有數據的情況下所應采取的行動
(1)如果msgflg和常數IPC_NOWAIT合用,則在msgsnd()執行時若是消息隊列已滿,則msgsnd()將不會阻塞,會立即返回-1。
(2)如果執行的是msgrcv(),則在消息隊列呈空時,不做等待馬上返回-1。
(3)當msgflg為0時,msgsnd()及msgrcv()在隊列呈滿或呈空的情形時,采取阻塞等待的處理模式。
3.設置消息隊列屬性
int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );
參數:
msgctl 系統調用對 msgqid 標識的消息隊列執行 cmd 操作,系統定義了 3 種 cmd 操作(1)IPC_STAT : 該命令用來獲取消息隊列對應的 msqid_ds 數據結構,并將其保存到 buf 指定的地址空間。
(2) IPC_SET : 該命令用來設置消息隊列的屬性,要設置的屬性存儲在buf中。
(3) IPC_RMID : 從內核中刪除 msqid 標識的消息隊列。
例子:
comm.h
#pragma once #include<sys/types.h> #include<sys/ipc.h> #include<stdio.h> #include<sys/msg.h> #include<string.h> #define _PATH_NAME_ "/tmp" #define _PROJ_ID_ 0x6666 #define _SIZE_ 1024 extern int serve_type; extern int client_type; struct msgbuf { long mtype; char mtext[_SIZE_]; }; int create_msg_queue(); int get_msg_queue(); void destory_msg_queue(int msg_id); void recv_msg_queue(int msg_id,char* out,int _type); int create_msg_queue(); void send_msg_queue(int msg_id,const char*msg,int _type);
comm.c
#include"comm.h" #include<stdio.h> #include<error.h> #include<sys/msg.h> #include<string.h> #include"comm.h" int serve_type=1; int client_type=2; static int comm_msg_queue(int flag) { key_t _key = ftok(_PATH_NAME_,_PROJ_ID_); if(_key<0) { perror("ftok"); return -1; } int msg_id = msgget(_key,IPC_CREAT | IPC_EXCL); if(msg_id < 0) { perror("msgget"); return -2; } return msg_id; } int create_msg_queue() { int flag = IPC_CREAT | IPC_EXCL|0666; return comm_msg_queue(flag); } int get_msg_queue() { int flag = IPC_CREAT; return comm_msg_queue(flag); } void destory_msg_queue(int msg_id) { if(msgctl(msg_id,IPC_RMID,NULL)<0) { perror("msgctl"); } } void send_msg_queue(int msg_id,const char*msg,int _type) { struct msgbuf data; memset(data.mtext,'\0',sizeof(data.mtext)); data.mtype = _type; strcpy(data.mtext,msg); if(msgsnd(msg_id,&data,sizeof(data.mtext),0)<0) { perror("msgsnd"); } } void recv_msg_queue(int msg_id,char* out,int _type) { struct msgbuf data; memset(data.mtext,'\0',sizeof(data.mtext)); data.mtype = _type; if(msgrcv(msg_id,&data,sizeof(data.mtext),_type,0)<0) { perror("msgrcv"); } else { strcpy(out,data.mtext); } }
serve.c
#include"comm.h" int main() { int msg_id = create_msg_queue(); if(msg_id < 0) { perror("msgget"); return 0; } int done = 0; char buf[_SIZE_]; while(!done) { memset(buf,'\0',sizeof(buf)); recv_msg_queue(msg_id,buf,client_type); printf("client#",buf); printf("Please Enter#"); fflush(stdout); ssize_t _s=read(0,buf,sizeof(buf)-1); if(_s > 0) { buf[_s]='\0';//bug } send_msg_queue(msg_id,buf,serve_type); } destory_msg_queue(msg_id); return 0; }
client.c
#include"comm.h" int main() { int msg_id = get_msg_queue(); int done = 0; char buf[_SIZE_]; while(!done) { printf("Please Enter#"); fflush(stdout); ssize_t _s=read(0,buf,sizeof(buf)-1); if(_s > 0) { buf[_s]='\0';//bug } send_msg_queue(msg_id,buf,client_type); memset(buf,'\0',sizeof(buf)); recv_msg_queue(msg_id,buf,serve_type); printf("serve#%s",buf); } destory_msg_queue(msg_id); return 0; }
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。