通过消息队列发送缓冲区

时间:2012-10-31 00:59:29

标签: c linux pointers ipc message-queue

您好我正在编写一个程序,通过消息队列发送一组字节,如此...

#include <sys/msg.h>
#include <stddef.h>

key_t key;
int msqid;
struct pirate_msgbuf pmb = {2, { "L'Olonais", 'S', 80, 10, 12035 } };

key = ftok("/home/beej/somefile", 'b');
msqid = msgget(key, 0666 | IPC_CREAT);

/* stick him on the queue */
msgsnd(msqid, &pmb, sizeof(struct pirate_msgbuf) - sizeof(long), 0);

以上示例是beejs网站上一个类似于我的简单程序。

我正在做的是发送带有类似结构的消息......

struct msg_queue{

    long message_type;
    char * buffer;

}

在发送我的msg_queue之前,我创建了一些替代缓冲区,其中包含各种信息,包括空字符等。现在当我做这样的事情......

struct msg_queue my_queue;
my_queue.message_type = 1;
my_queue.buffer = "My message";
msgsnd(mysqid, &pmb, sizeof(struct msg_queue) - sizeof(long), 0);

接收指针并读取存储在该字符串中的值没有问题。但是,如果我要做类似的事情......

struct msg_queue my_queue;
my_queue.message_type = 1;
my_queue.buffer = sum_buffer_with_lots_of_weird_values; // of type char *
msgsnd(mysqid, &pmb, sizeof(struct msg_queue) - sizeof(long), 0);

我通过队列传递给其他进程的指针将读取垃圾而不是存储的值。我尝试将我的任意数组作为静态char *,但这也无济于事。如何通过队列正确传入缓冲区?感谢。

3 个答案:

答案 0 :(得分:4)

你不应该发送指向另一个进程的指针,它们在另一个进程的地址空间中没有任何意义(或指向一些非常不同的东西)。

消息队列对于无限数据(如可变长度字符串)不是很好。将指针更改为足够大的固定长度char数组,以容纳最大的字符串,并在写入队列之前将字符串复制到数组中。或者使用其他类型的IPC,例如域套接字。

答案 1 :(得分:2)

Message Queue用于进程间通信。 当您在一个进程中对某些内存进行malloc时,它只存在于其他进程无法访问的进程内存空间中。

当您将指针发送过来时,您将发送一个无法访问的地址空间。它甚至可能导致分段错误。

一种方法是限制缓冲区大小(如果适用)。

struct msg_queue {

long message_type;
char buffer[MAX_LEN];

}

另一种方法是发送2次。第一个msgsnd,发送缓冲区的大小。 下一次发送,使用第一次发送的大小发送char数组。 :)

在收到结束时,首先获得大小,然后接收缓冲区。

其他方式是使用管道或插座。

答案 2 :(得分:1)

“msgsend()”只会读取缓冲区中的字节。

如果其中一个字节恰好是一个指针(某个字符串或其他地方的对象)...猜猜是什么 - 接收器只会得到二进制指针。不是指向的数据。

您需要做的是将消息的整个内容打包到缓冲区中,然后发送该线性缓冲区。