导航:首页 > 编程语言 > linux消息队列编程

linux消息队列编程

发布时间:2023-07-25 21:19:45

㈠ 如何用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我,别忘了加分。

阅读全文

与linux消息队列编程相关的资料

热点内容
汽车导航不读文件夹 浏览:107
全球云服务器如何注册 浏览:884
udp直播流如何在服务器里播放器 浏览:591
macbrew安装php 浏览:425
点特征提取算法 浏览:502
python弹窗显示输入的文字 浏览:751
python数字和中文互转 浏览:639
汽车空调压缩机外壳 浏览:458
大型服务器都是采用什么模式 浏览:5
服务器为什么跳闸 浏览:398
怎么用python分析基金收益 浏览:990
couple算法 浏览:791
android调用文件管理器 浏览:152
中国我的世界最大的小游戏服务器地址 浏览:833
程序员爆破粒子 浏览:889
我的世界pcl启动器怎么加入服务器 浏览:253
传奇源码扩充人物结构 浏览:844
购买多个文件夹 浏览:774
其他app如何投屏到微光视频教学 浏览:340
车辆不解压会给大绿本吗 浏览:789