其中数字 1 表示类型为 1 的消息,数字2、3、4 类似。彩色块表示消息数据,它们被挂在对应类型的链表上。
值得注意的是,刚刚说过没有消息类型为 0 的消息,实际上,消息类型为 0 的链表记录了所有消息加入队列的顺序,其中红色箭头表示消息加入的顺序。
无论你是发送还是接收消息,消息的格式都必须按照规范来。简单的说,它一般长成下面这个样子:
所以,只要你保证首4字节(32 位 linux 下的 long)是一个整数就行了。
举个例子:
从上面可以看出,正文部分是什么数据类型都没关系,因为消息队列传递的是 2 进制数据,不一定非得是文本。
msgsnd 函数用于将数据发送到消息队列。如果该函数被信号打断,会设置 errno 为 EINTR。
参数 msqid:ipc 内核对象 id
参数 msgp:消息数据地址
参数 msgsz:消息正文部分的大小(不包含消息类型)
参数 msgflg:可选项
该值为 0:如果消息队列空间不够,msgsnd 会阻塞。
IPC_NOWAIT:直接返回,如果空间不够,会设置 errno 为 EAGIN.
返回值:0 表示成功,-1 失败并设置 errno。
msgrcv 函数从消息队列取出消息后,并将其从消息队列里删除。
参数 msqid:ipc 内核对象 id
参数 msgp:用来接收消息数据地址
参数 msgsz:消息正文部分的大小(不包含消息类型)
参数 msgtyp:指定获取哪种类型的消息
msgtyp = 0:获取消息队列中的第一条消息
msgtyp >0:获取类型为 msgtyp 的第一条消息,除非指定了 msgflg 为MSG_EXCEPT,这表示获取除了 msgtyp 类型以外的第一条消息。
msgtyp <0:获取类型 ≤|msgtyp|≤|msgtyp| 的第一条消息。
参数 msgflg:可选项。
如果为 0 表示没有消息就阻塞。
IPC_NOWAIT:如果指定类型的消息不存在就立即返回,同时设置 errno 为 ENOMSG
MSG_EXCEPT:仅用于 msgtyp >0 的情况。表示获取类型不为 msgtyp 的消息
MSG_NOERROR:如果消息数据正文内容大于 msgsz,就将消息数据截断为 msgsz
程序 msg_send 和 msg_recv 分别用于向消息队列发送数据和接收数据。
msg_send 程序定义了一个结构体 Msg,消息正文部分是结构体 Person。该程序向消息队列发送了 10 条消息。
msg_send.c
程序 msg_send 第一次运行完后,内核中的消息队列大概像下面这样:
msg_recv 程序接收一个参数,表示接收哪种类型的消息。比如./msg_recv 4 表示接收类型为 4 的消息,并打印在屏幕。
先运行 msg_send,再运行 msg_recv。
接收所有消息
接收类型为 4 的消息
获取和设置消息队列的属性
msqid:消息队列标识符
cmd:控制指令
IPC_STAT:获得msgid的消息队列头数据到buf中
IPC_SET:设置消息队列的属性,要设置的属性需先存储在buf中,可设置的属性包括:msg_perm.uid、msg_perm.gid、msg_perm.mode以及msg_qbytes
buf:消息队列管理结构体。
返回值:
成功:0
出错:-1,错误原因存于error中
EACCESS:参数cmd为IPC_STAT,确无权限读取该消息队列
EFAULT:参数buf指向无效的内存地址
EIDRM:标识符为msqid的消息队列已被删除
EINVAL:无效的参数cmd或msqid
EPERM:参数cmd为IPC_SET或IPC_RMID,却无足够的权限执行
两个进程用相同的key,就能共享了。 之后就能通讯了。例如下面用1234做key
//接收方msgid = msgget((key_t)1234, 0666 | IPC_CREAT)
if(msgrcv(msgid, (void*)&data, BUFSIZ, msgtype, 0) == -1)
{
fprintf(stderr, "msgrcv failed with errno: %d\n", errno)
exit(EXIT_FAILURE)
} //发送方
msgid = msgget((key_t)1234, 0666 | IPC_CREAT)
if(msgsnd(msgid, (void*)&data, MAX_TEXT, 0) == -1)
{
fprintf(stderr, "msgsnd failed\n")
exit(EXIT_FAILURE)
}
消息队列就是用来进程间通信的, 每个进程只要知道消息队列的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
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)