㈠ 如何用JAVA實現linux上的消息隊列功能
下面來說說如何用不用消息隊列來進行進程間的通信,消息隊列與命名管道有很多相似之處。有關命名管道的更多內容可以參閱我的另一篇文章:Linux進程間通信——使用命名管道
一、什麼是消息隊列
消息隊列提供了一種從一個進程向另一個進程發送一個數據塊的方法。 每個數據塊都被認為含有一個類型,接收進程可以獨立地接收含有不同類型的數據結構。我們可以通過發送消息來避免命名管道的同步和阻塞問題。但是消息隊列與命名管道一樣,每個數據塊都有一個最大長度的限制。
Linux用宏MSGMAX和MSGMNB來限制一條消息的最大長度和一個隊列的最大長度。
二、在Linux中使用消息隊列
Linux提供了一系列消息隊列的函數介面來讓我們方便地使用它來實現進程間的通信。它的用法與其他兩個System V PIC機制,即信號量和共享內存相似。
1、msgget函數
該函數用來創建和訪問一個消息隊列。它的原型為:
int msgget(key_t, key, int msgflg);
與其他的IPC機制一樣,程序必須提供一個鍵來命名某個特定的消息隊列。msgflg是一個許可權標志,表示消息隊列的訪問許可權,它與文件的訪問許可權一樣。msgflg可以與IPC_CREAT做或操作,表示當key所命名的消息隊列不存在時創建一個消息隊列,如果key所命名的消息隊列存在時,IPC_CREAT標志會被忽略,而只返回一個標識符。
它返回一個以key命名的消息隊列的標識符(非零整數),失敗時返回-1.
2、msgsnd函數
該函數用來把消息添加到消息隊列中。它的原型為:
int msgsend(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);
msgid是由msgget函數返回的消息隊列標識符。
msg_ptr是一個指向准備發送消息的指針,但是消息的數據結構卻有一定的要求,指針msg_ptr所指向的消息結構一定要是以一個長整型成員變數開始的結構體,接收函數將用這個成員來確定消息的類型。所以消息結構要定義成這樣:
struct my_message{
long int message_type;
/* The data you wish to transfer*/
};
msg_sz是msg_ptr指向的消息的長度,注意是消息的長度,而不是整個結構體的長度,也就是說msg_sz是不包括長整型消息類型成員變數的長度。
msgflg用於控制當前消息隊列滿或隊列消息到達系統范圍的限制時將要發生的事情。
如果調用成功,消息數據的一分副本將被放到消息隊列中,並返回0,失敗時返回-1.
3、msgrcv函數
該函數用來從一個消息隊列獲取消息,它的原型為
int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg);
msgid, msg_ptr, msg_st的作用也函數msgsnd函數的一樣。
msgtype可以實現一種簡單的接收優先順序。如果msgtype為0,就獲取隊列中的第一個消息。如果它的值大於零,將獲取具有相同消息類型的第一個信息。如果它小於零,就獲取類型等於或小於msgtype的絕對值的第一個消息。
msgflg用於控制當隊列中沒有相應類型的消息可以接收時將發生的事情。
調用成功時,該函數返回放到接收緩存區中的位元組數,消息被復制到由msg_ptr指向的用戶分配的緩存區中,然後刪除消息隊列中的對應消息。失敗時返回-1.
4、msgctl函數
該函數用來控制消息隊列,它與共享內存的shmctl函數相似,它的原型為:
int msgctl(int msgid, int command, struct msgid_ds *buf);
command是將要採取的動作,它可以取3個值,
IPC_STAT:把msgid_ds結構中的數據設置為消息隊列的當前關聯值,即用消息隊列的當前關聯值覆蓋msgid_ds的值。
IPC_SET:如果進程有足夠的許可權,就把消息列隊的當前關聯值設置為msgid_ds結構中給出的值
IPC_RMID:刪除消息隊列
buf是指向msgid_ds結構的指針,它指向消息隊列模式和訪問許可權的結構。msgid_ds結構至少包括以下成員:
struct msgid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
};
成功時返回0,失敗時返回-1.
三、使用消息隊列進行進程間通信
馬不停蹄,介紹完消息隊列的定義和可使用的介面之後,我們來看看它是怎麼讓進程進行通信的。由於可以讓不相關的進程進行行通信,所以我們在這里將會編寫兩個程序,msgreceive和msgsned來表示接收和發送信息。根據正常的情況,我們允許兩個程序都可以創建消息,但只有接收者在接收完最後一個消息之後,它才把它刪除。
接收信息的程序源文件為msgreceive.c的源代碼為:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/msg.h>
struct msg_st
{
long int msg_type;
char text[BUFSIZ];
};
int main()
{
int running = 1;
int msgid = -1;
struct msg_st data;
long int msgtype = 0; //注意1
//建立消息隊列
msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
if(msgid == -1)
{
fprintf(stderr, "msgget failed with error: %d\n", errno);
exit(EXIT_FAILURE);
}
//從隊列中獲取消息,直到遇到end消息為止
while(running)
{
if(msgrcv(msgid, (void*)&data, BUFSIZ, msgtype, 0) == -1)
{
fprintf(stderr, "msgrcv failed with errno: %d\n", errno);
exit(EXIT_FAILURE);
}
printf("You wrote: %s\n",data.text);
//遇到end結束
if(strncmp(data.text, "end", 3) == 0)
running = 0;
}
//刪除消息隊列
if(msgctl(msgid, IPC_RMID, 0) == -1)
{
fprintf(stderr, "msgctl(IPC_RMID) failed\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
發送信息的程序的源文件msgsend.c的源代碼為:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/msg.h>
#include <errno.h>
#define MAX_TEXT 512
struct msg_st
{
long int msg_type;
char text[MAX_TEXT];
};
int main()
{
int running = 1;
struct msg_st data;
char buffer[BUFSIZ];
int msgid = -1;
//建立消息隊列
msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
if(msgid == -1)
{
fprintf(stderr, "msgget failed with error: %d\n", errno);
exit(EXIT_FAILURE);
}
//向消息隊列中寫消息,直到寫入end
while(running)
{
//輸入數據
printf("Enter some text: ");
fgets(buffer, BUFSIZ, stdin);
data.msg_type = 1; //注意2
strcpy(data.text, buffer);
//向隊列發送數據
if(msgsnd(msgid, (void*)&data, MAX_TEXT, 0) == -1)
{
fprintf(stderr, "msgsnd failed\n");
exit(EXIT_FAILURE);
}
//輸入end結束輸入
if(strncmp(buffer, "end", 3) == 0)
running = 0;
sleep(1);
}
exit(EXIT_SUCCESS);
}
轉載僅供參考,版權屬於原作者。祝你愉快,滿意請採納哦
㈡ 請教一個關於linux消息隊列的問題
一般使用步驟:
1. 用ftok產生一個key。
2. 調用msgget(使用key作為參數)產生一個隊列
3. 進程可以用msgsnd發送消息到這個隊列,相應的別的進程用msgrcv讀取。
這里需要注意msgsnd可能會失敗的兩個情況:
a) 可能被中斷打斷(包括msgsnd和msgrcv). 尤其是大流量應用中更容易出現. 比較安全的用法是判斷操作是否被中斷打斷,如果被打斷, 則需要繼續嘗試。
b) 消息隊列滿。產生這個錯誤,則需要考慮提高系統消息隊列規格,或者查看消息接收處是否有問題
4. msgctl函數可以用來刪除消息隊列
消息隊列產生之後,除非明確的刪除(可以用),產生的隊列會一直保留在系統中。linux下消息隊列的個數是有限的,注意不要泄露。如果 使用已經達到上限,msgget調用會失敗,產生的錯誤碼對應的提示信息為no space left on device.
注意點:
1.消息的類型 mtype 不需為非0值。如果使用0,則msgsnd會失敗,並得到」Invalid argument「錯誤。
2.msgflg為0表示阻塞等待,如果msgflg為IPC_NOWAIT表示非阻塞。
3.最好使用root許可權執行消息隊列,否則msgrcv 提示 "Permission denied"。
㈢ linux系統編程中的消息隊列該怎麼使用呀
消息隊列用於進程間通信,每個進程可以,只要該消息queueID隊列
的#ifndef CMSGOP_H
#定義CMSGOP_H
#包括類型。 H>
#包括ipc.h>
#包括msg.h>中
類CMsgOp
{
公眾:
CMsgOp ();
虛擬CMsgOp();
typedef結構_customMessageFormat {
整數PROCESSID;
整數CMD;
整數commandArg;
} CCustomMessageFormat; BR p>詮釋的init();
整數發送(常量CCustomMessageFormat&消息);
整數接收(CCustomMessageFormat&消息);
私人:
整數msgQueueID;
結構msgbuf sendBuf;
結構msgbuf recvBuf;
};
#ENDIF / / CMSGOP_H
的#include「 cmsgop.h「
#包括中
#包括中
#包括中
CMsgOp :: CMsgOp()
> {
}
CMsgOp ::CMsgOp()
{
了msgctl(msgQueueID,IPC_RMID,NULL);
}
BR />整型CMsgOp :: init()中
的key_t的key = ftok的(「/ home/maemo/tmp2」,1);
如果(-1 ==鍵) {
PERROR(「ftok的失敗!」);
返回-1;
}
整數RET = msgget(鍵,IPC_CREAT);
>如果(-1 == RET)
{
PERROR(「創建消息隊列失敗!」);
返回-1;
}
msgQueueID = RET;
返回0;
}
整數CMsgOp ::發送(常量CCustomMessageFormat&消息)
{的memcpy(sendBuf.mtext,及訊息,大小(CCustomMessageFormat));
sendBuf.mtype = 1;
整數RET =的msgsnd(msgQueueID,&sendBuf,大小(CCustomMessageFormat),0);
如果(-1 = = RET)
{
PERROR(「消息發送失敗!」);
返回RET;
}
}
整數CMsgOp: :接收(CCustomMessageFormat&消息)
{
整數RET =的msgrcv(msgQueueID,與recvBuf,大小(CCustomMessageFormat),0,IPC_NOWAIT);
如果( - 1 == RET) {
PERROR(「接收消息失敗!」);
返回-1;
}
的memcpy(&消息,recvBuf.mtext,大小(CCustomMessageFormat ));
返回RET;
}
㈣ Linux下編程消息隊列怎麼封裝較好,怎麼保證2個進程能用同一個消息隊列
消息隊列就是用來進程間通信的, 每個進程只要知道消息隊列的queueID即可
#ifndef CMSGOP_H
#define CMSGOP_H
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
class CMsgOp
{
public:
CMsgOp();
virtual ~CMsgOp();
typedef struct _customMessageFormat{
int processID;
int cmd;
int commandArg;
}CCustomMessageFormat;
int init();
int send(const CCustomMessageFormat &message);
int receive(CCustomMessageFormat &message);
private:
int msgQueueID;
struct msgbuf sendBuf;
struct msgbuf recvBuf;
};
#endif // CMSGOP_H
#include "cmsgop.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
CMsgOp::CMsgOp()
{
}
CMsgOp::~CMsgOp()
{
msgctl(msgQueueID, IPC_RMID, NULL);
}
int CMsgOp::init()
{
key_t key = ftok("/home/maemo/tmp2", 1);
if(-1 == key)
{
perror("ftok failed!");
return -1;
}
int ret = msgget(key, IPC_CREAT);
if(-1 == ret)
{
perror("create message queue failed!");
return -1;
}
msgQueueID = ret;
return 0;
}
int CMsgOp::send(const CCustomMessageFormat &message)
{
memcpy(sendBuf.mtext, &message, sizeof(CCustomMessageFormat));
sendBuf.mtype = 1;
int ret = msgsnd(msgQueueID, &sendBuf, sizeof(CCustomMessageFormat), 0);
if(-1 == ret)
{
perror("message send failed!");
return ret;
}
}
int CMsgOp::receive(CCustomMessageFormat &message)
{
int ret = msgrcv(msgQueueID, &recvBuf, sizeof(CCustomMessageFormat), 0, IPC_NOWAIT);
if(-1 == ret)
{
perror("receive message failed!");
return -1;
}
memcpy(&message, recvBuf.mtext, sizeof(CCustomMessageFormat));
return ret;
}
㈤ 高手進!在Linux系統中用消息隊列實現兩個進程之間的信息傳輸的一個小程序,幫忙改下錯,急!!!!
你只在
server
進程中(對應spid==0),調用
open_queue
來打開
消息隊列
,即msqid只在這個進程中有效,在host進程中(對應cpid==0),由於msqid無效,所以無法發送消息。
解決方法:只要把
do
{
msqid
=
open_queue(key);
}
while
(msqid
==
-1);
這段代碼移到第一個fork之前,這樣所有的進程中的msqid就都指向那個隊列了。
還有問題可以
hi我,別忘了加分。