Linux进程间通信——消息队列应用实例

    消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。下面是两个测试模块

接收模块

msgreceive.c 的代码如下

/*============================================================================= 
#     FileName: msgreceive.c
#         Desc: receice message from message queue 
#       Author: Licaibiao 
#      Version:  
#   LastChange: 2017-01-20
#      History: 
=============================================================================*/

#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[128];
};

int main()
{
	int running = 1;
	int msgid = -1;
	int len = 0;
	long int msgtype = 5; 
	struct msg_st data;
		
	msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
	if(-1 == msgid )
	{
		fprintf(stderr, "msgget failed with error: %d\n", errno);
		exit(EXIT_FAILURE);
	}
	
	while(running)
	{
		memset(&data.text, 0, 128);
		len = msgrcv(msgid, (void*)&data, 128, msgtype, 0);
		if(-1 == len)
		{
			fprintf(stderr, "msgrcv failed with errno: %d\n", errno);
			exit(EXIT_FAILURE);
		}
		printf("You wrote: %s\n",data.text);

		if(0 == strncmp(data.text, "end", 3))
			running = 0;
	}

	//remove message queue
	if(-1 == msgctl(msgid, IPC_RMID, 0))
	{
		fprintf(stderr, "msgctl(IPC_RMID) failed\n");
		exit(EXIT_FAILURE);
	}
	exit(EXIT_SUCCESS);
}



发送模块

/*=============================================================================
#     FileName: msgsend.c
#         Desc: send data to message queue
#       Author: Licaibiao
#      Version: 
#   LastChange: 2017-01-20 
#      History:
=============================================================================*/

#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;
	int len;

	msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
	if(msgid == -1)
	{
		fprintf(stderr, "msgget failed with error: %d\n", errno);
		exit(EXIT_FAILURE);
	}

	while(running)
	{
		
		printf("Enter data : ");
		fgets(buffer, BUFSIZ, stdin);
		data.msg_type = 5;    
		strcpy(data.text, buffer);
	    len = strlen(data.text);	
		if(msgsnd(msgid, (void*)&data, len-1, 0) == -1)
		{
			fprintf(stderr, "msgsnd failed\n");
			exit(EXIT_FAILURE);
		}
		
		if(strncmp(buffer, "end", 3) == 0)
			running = 0;
		usleep(100000);
	}
	exit(EXIT_SUCCESS);
}

编译执行结果如下:

root@ubuntu:/home/test/msg_test# gcc msgsend.c  -o send 
root@ubuntu:/home/test/msg_test# gcc msgreceive.c -o recv 
root@ubuntu:/home/test/msg_test# ./recv &
[1] 106594
root@ubuntu:/home/ysj000/quanzhiSDK/F25_test/test/msg_test# ./send 
Enter data : hello
You wrote: hello
Enter data : test
You wrote: test
Enter data : hello world
You wrote: hello world
Enter data : end
You wrote: end
[1]+  Done                    ./recv
root@ubuntu:/home/test/msg_test# 
    这里需要注意,在接收端消息队列类型中的msg_type,如果设置为0,则表示接收所有的消息。如果非零,则只接收与发送端类型一样的消息。比如接收端设置为3,那么接收端只接收发送端msg_type为3进程发送过来的消息。

与命名管道相比,消息队列的优势在于:

1、消息队列也可以独立于发送和接收进程而存在,从而消除了在同步命名管道的打开和关闭时可能产生的困难。

2、同时通过发送消息还可以避免命名管道的同步和阻塞问题,不需要由进程自己来提供同步方法。

3、接收程序可以通过消息类型有选择地接收数据,而不是像命名管道中那样,只能默认地接收。



猜你喜欢

转载自blog.csdn.net/li_wen01/article/details/54632198