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
函數

相關文章
相關標籤/搜索