IPC研究(6) -- 消息队列(message queue)

"In many ways, message queues are like named pipes, but without the complexity associated with opening and closing the pipe.
However, using messages doesn’t get you away from the problems that you have with named pipes,
such as blocking on full pipes.
Message queues provide a reasonably easy and efficient way of passing data between two unrelated
processes. They have the advantage over named pipes that the message queue exists independently of
both the sending and receiving processes, which removes some of the difficulties that occur in synchronizing the opening and closing of named pipes."
以上这段话摘自"Linux程序设计“。对于named pipe的开关同步,真心有点麻烦,若是处理很差,就会致使两个进程互锁。简单示例:
processA |-- named pipe1 --| processB
         |-- named pipe2 --|
A打开pipe1来读(action1),而后打开pipe2来写(action2)。
B打开pipe2来读(action3),而后打开pipe1来写(action4)。
以上这种状况,死锁必然发生!(固然,若是你用nonblock方式打开就另说了。)

#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
int msgget(key_t key, int msgflg);
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_t msg_sz, int msgflg);
函数原型。和semaphore以及shared memory很像,没什么特别的。(不愧都是system V一族的。)

struct my_message {
long int message_type;
/* The data you wish to transfer */
}
message必需要以long int开头。能够用它来实现简单优先级队列。

If you simply want to retrieve messages in
the order in which they were sent, set msgtype to 0. If you want to retrieve only messages with a specific message type, set msgtype equal to that value. If you want to receive messages with a type of n or smaller, set msgtype to -n.

而后,无耻又无聊的照书上抄了一个例子:ide

/**recv**/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/msg.h>

struct my_msg_st
{
	long int my_msg_type;
	char sometext[BUFSIZ];
};

int main()
{
	int running = 1;
	int msgid;
	struct my_msg_st msg;
	long int msg_to_recv = 0;

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

	while (running)
	{
		if (msgrcv(msgid, (void*)&msg, BUFSIZ, 
			   msg_to_recv, 0) == -1)
		{
			fprintf(stderr, "msgrcv failed with error %d \n", errno);
			exit(EXIT_FAILURE);
		}
		printf("You wrote: %s", msg.sometext);
		if (strncmp(msg.sometext, "end", 3) == 0)
		{
			running = 0;
		}
	}

	if (msgctl(msgid, IPC_RMID, 0) < 0)
	{
		fprintf(stderr, "msgctl(IPC_RMID) failed\n");
		exit(EXIT_FAILURE);
	}

	exit(EXIT_SUCCESS);
}

/**send**/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/msg.h>

#define MAX_TEXT 512

struct my_msg_st
{
	long int my_msg_type;
	char sometext[BUFSIZ];
};


int main()
{
	int running = 1;
	int msgid;
	struct my_msg_st msg;
	char buf[BUFSIZ];

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

	while (running)
	{
		printf("Enter some text: ");
		fgets(buf, BUFSIZ, stdin); /* fgets add \0 to the end of the buf */
		msg.my_msg_type = 1;
		strcpy(msg.sometext, buf);

		if (msgsnd(msgid, (void *)&msg, MAX_TEXT, 0) < 0)
		{
			fprintf(stderr, "msgsnd failed\n");
			exit(EXIT_FAILURE);
		}
		if (strncmp(buf, "end", 3)==0)
		{
			running = 0;
		}
	}
	exit(EXIT_SUCCESS);
}

结果:
chenqi@chenqi-laptop ~/MyPro/CFiles/IPC/msg_queue $ ./recv &
[1] 19084
chenqi@chenqi-laptop ~/MyPro/CFiles/IPC/msg_queue $ ./send
Enter some text: hello
Enter some text: You wrote: hello
nice
Enter some text: You wrote: nice
to
Enter some text: You wrote: to
meet
Enter some text: You wrote: meet
you
Enter some text: You wrote: you
end
You wrote: end
[1]+  Done                    ./recv
函数

相关文章
相关标签/搜索