SystemV消息队列
简介
消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向中按照一定的规则添加新消息;有读权限的进程则可以读走消息。读走就没有了。消息队列是随内核持续的。 只有内核重启或人工删除时,该消息才会被删除。在系统范围内,消息队列与键值唯一对应。
msgctl(int msqid, int cmd, struct msqid_ds *buf);>//消息队列的控制函数//command是将要采取的动作,它可以取3个值,
//IPC_STAT:把msgid_ds结构中的数据设置为消息队列的当前关联值,即用消息队列的当前关联值覆盖msgid_ds的值。
//IPC_SET:如果进程有足够的权限,就把消息列队的当前关联值设置为msgid_ds结构中给出的值
//IPC_RMID:删除消息队列</span>
int msgget(key_t key, int msgflg);//创建访问一个消息队列 </span></div>//msgflg是一个权限标志,表示消息队列的访问权限,它与文件的访问权限一样。msgflg可以与IPC_CREAT做或操作,表示当key所命名的消息队列不存在时创建一个消息队列,如果key所命名的消息队列存在时,IPC_CREAT标志会被忽略,而只返回一个标识符。使用IPC_EXCL可以保证每次打开操作的的MQ都是最新打开的。
int msgrcv(int msqid, void *msg_ptr, size_t msg_sz, long int msgtype, int msgflg);//从一个消息队列中获取消息
int msgsnd(int msqid, const void *msg_ptr,size_tmsg_sz,int msgflg);//把消息添加到消息队列中
//msg_ptr规定了必须指向以long类型变量开头的结构体,表示msg_type
//msgflg用于控制当前消息队列满或队列消息到达系统范围的限制时将要发生的事情
//msgmax:该文件指定了从一个进程发送到另一个进程的消息的最大长度。
//msgmni:该文件指定消息队列标识的最大数目。
//msgmnb:该文件指定在一个消息队列中最大的字节数。
//调用完msgrcv后会将相应消息从队列中删除
//更多内容可以通过linux终端下man命令来获取</span>
注:msgtype可以实现一种简单的接收优先级。如果msgtype为0,就获取队列中的第一个消息。如果它的值大于零,将获取具有相同消息类型的第一个信息。如果它小于零,就获取类型等于或小于msgtype的绝对值的第一个消息。
注:通过cat /proc/sys/kernel/msgmax(msgmnb/msgmni)
msgmax:该文件指定了从一个进程发送到另一个进程的消息的最大长度。
msgmni:该文件指定消息队列标识的最大数目。
msgmnb:该文件指定在一个消息队列中最大的字节数。
非亲缘进程通信测试源文件
send
/*===============================================================
* Copyright (C) 2014 All rights reserved.
*
* 文件名称:mq_send.c
* 创 建 者:张 笑
* 创建日期:2014年12月26日
* 描 述:message_q IPC send
*
* 更新日志:
*
================================================================*/
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#define MSGKEY 1024//another choice
#define BUFSIZE 1024*4
#define PATHNAME "."
typedef struct _msgstru
{
unsigned int msg_id;
char msg_context[BUFSIZE];
}MSG;
int main()
{
MSG msgs;
int temp_id;
int ret_send;
char temp_context[256];
int msqid;
key_t key;
//init
temp_id=0;
memset(&msgs,0x00,sizeof(MSG));
memset(temp_context,0x00,256);
key = ftok(PATHNAME,0);
assert(key!=-1);
msqid=msgget(key,IPC_EXCL);//if MQ exist?
if(msqid < 0)
{
msqid = msgget(key,IPC_CREAT|0666);
assert(msqid != -1);
}
temp_id=253;
strcpy(temp_context,"helloworld253");
msgs.msg_id=temp_id;
strcpy(msgs.msg_context,temp_context);
ret_send=msgsnd(msqid,&msgs,sizeof(MSG),IPC_NOWAIT);
assert(ret_send != -1);
temp_id=254;
strcpy(temp_context,"helloworld254");
msgs.msg_id=temp_id;
strcpy(msgs.msg_context,temp_context);
ret_send=msgsnd(msqid,&msgs,sizeof(MSG),IPC_NOWAIT);
assert(ret_send != -1);
temp_id=255;
strcpy(temp_context,"helloworld255");
msgs.msg_id=temp_id;
strcpy(msgs.msg_context,temp_context);
ret_send=msgsnd(msqid,&msgs,sizeof(MSG),IPC_NOWAIT);
assert(ret_send != -1);
return 0;
}
receive
/*===============================================================
* Copyright (C) 2014 All rights reserved.
*
* 文件名称:mq_send.c
* 创 建 者:张 笑
* 创建日期:2014年12月26日
* 描 述:message_q IPC receive
*
* 更新日志:
*
================================================================*/
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#define MSGKEY 1024//another choice
#define BUFSIZE 1024*5
#define PATHNAME "."
typedef struct __msgstru
{
unsigned int msg_id;
char msg_context[BUFSIZE];
}MSG;
int main(int argc, char *argv[])
{
MSG msgs;
int ret_recv;
int msqid;
int msg_id;
key_t key;
memset(&msgs,0x00,sizeof(MSG));
key=ftok(PATHNAME,0);
assert(key!=-1);
msqid=msgget(key,IPC_EXCL);//if MQ exist?
assert(msqid != -1);
while(1){
scanf("%d",&msg_id);
ret_recv=msgrcv(msqid,&msgs,sizeof(MSG),msg_id,0);
assert(ret_recv != -1);
printf("msg_id=%d,msg_context=%s\r\n",msgs.msg_id,msgs.msg_context);
memset(&msgs,0x00,sizeof(MSG));
}
msgctl(msqid,IPC_RMID,0);//delete MQ
return 0;
}
Makefile
CROSS = gcc
flags=-o
all: mq_send mq_receive
mq_receive:mq_receive.c
$(CROSS) $(flags) mq_receive mq_receive.c
mq_send:mq_send.c
$(CROSS) $(flags) mq_send mq_send.c
clean:
rm -rf mq_receive mq_send
Stack smashing detected解决方案
接收方能够正确收到并打印发送方的数据,但是在打印完成后,会出现Stack smashing detected的错误。
最终的解决方案:接收方用于从MQ收数据的内存分配不够,将接收端的buffer size开大一点(比发送方大)即可。