Linux下消息队列学习(2)

一、消息队列系统参数设置
在Linux系统下有两个参数可以设置消息队列的大小:

vim /etc/sysctl.conf

加入:

# Controls the default maxmimum size of a mesage queue
kernel.msgmnb = 6553600

# Controls the maximum size of a message, in bytes
kernel.msgmax = 65536

参数说明:
kernel.msgmnb:每个消息队列的大小(字节)
kernel.msgmax:消息队列中一个消息的最大长度(字节)

按照以上设置,一个消息队列最大长度可以为6553600字节,每个消息最大长度65536字节,所以该消息队列可存储100条消息。

二、消息队列的特点
1)消息队列就是一个消息的链表。消息队列允许一个或多个进程向它写入或读取消息,而且消息是按消息类型访问与写入。如果读队列使用的消息类型为0,则读取消息队列中的第一条消息。
2)消息队列是随内核持续的,即当使用该消息队列的进程结束,或者已关闭该消息队列,该队列中的消息不会随之消失,只有在内核重新初始化,即计算机重启之后才会消失,因此成为内核的持续性,这点也是与管道和FIFO的区别。
3)消息队列的另一个特性是,在某一个进程往消息队列写消息之前不需要另外某个进程在该消息队列上等待消息的到达,即不会像管道、FIFO那样,如果往管道和FIFO写数据时,如果没有一个进程已经将读端打开,那么写操作会被阻塞。当然如果从消息队列读取数据时,消息队列为空时可以按设置的flag决定是否阻塞。

三、取指定的消息类型
例子程序:test5.c

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

typedef struct
{
	long mtype;
	char mbuf[1024];
}mymsg;

int main(void)
{
	int i;
	int msgid;
	mymsg message[3];
	
	printf("this is test5!\n");
	
	message[0].mtype = 100;
	memcpy(message[0].mbuf, "this is 100 message", 19);
	message[1].mtype = 101;
	memcpy(message[1].mbuf, "this is 101 message", 19);
	message[2].mtype = 102;
	memcpy(message[2].mbuf, "this is 102 message", 19);
	
	msgid = msgget(1004, 0666|IPC_CREAT);//key 1004
	if (msgid < 0)
	{
		printf("create key=1004 error, errno=%d\n", errno);
		exit(-1);
	}
	
	for (i = 0; i < 3; i++)
	{
		msgsnd(msgid, (void *)&message[i], strlen(message[i].mbuf)+1, 0);
	}
	
	return 0;
}


例子程序:test6.c

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

typedef struct
{
	long mtype;
	char mbuf[1024];
}mymsg;

int main(void)
{
	int i, j;
	mymsg message;
	
	printf("this is test6!\n");
	
	i = msgget(1004, 0666|IPC_CREAT);
	if (i < 0)
	{
		printf("create key=1004 error, errno=%d\n", errno);
		exit(-1);
	}
	
	//test6进程在key=1004的消息队列上取指定类型的消息
	j = msgrcv(i, (void *)&message, 1024, 101, 0);
	if (j < 0)
	{
		printf("rev error, errno=%d\n", errno);
		exit(-1);
	}
	else
	{
		//显示取出的消息
		printf("%s\n", message.mbuf);
	}
	
	return 0;
}


test5执行结果:

[root@server ~]# ./test5
this is test5!

test6执行结果:

[root@server ~]# ./test6
this is test6!
this is 101 message

test6取到了type为101的这条消息。

四、消息队列使用的方式
在一个多进程的Linux应用系统程序中,可以为每个进程定义一个id号,把这个id号作为key建立消息队列。并且约定每个进程只能从自己key对应的消息队列中读消息,对其它进程的消息队列写消息。
本进程的消息类型也可以用这个id号来标识。而id号、进程和消息队列的对应关系可以在数据库中建张表来维护。

参考资料:
http://blog.chinaunix.net/uid-26790551-id-3175204.html