C语言 无法正确使用mqueue

0tdrvxhp  于 2023-03-07  发布在  其他
关注(0)|答案(1)|浏览(162)

我正在尝试理解如何使用mqueue.h在工作线程之间进行通信。我知道mqueue.h是为进程通信而设计的,而不是线程,但它是我能找到的唯一posix队列API,因为我不能使用外部库。
我写了这段测试代码,但是由于某种原因,接收到的值和发送的值不一样。这段代码的目的是发送一个指针到另一个线程。

#include <stdio.h>
#include <errno.h>
#include <mqueue.h>
#include <pthread.h>
#include <fcntl.h>

typedef struct {
    mqd_t id;
    char* name;
} thread_data;

struct mq_attr attr = {0, 10, sizeof(char*), 0};

void *new_thread(void *arg) {
    char* pArg;
    thread_data *pData;
    int res;

    printf("Waiting to receive message (queue %d)...\n", *(mqd_t*)arg);
    fflush(stdout);
    res = mq_receive(*(mqd_t*)arg, pArg, sizeof(char*), NULL);

    if (res != -1)
    {
        pData = (thread_data*)pArg;
        printf("Message received in %p: %s\n", pData, pData->name);
    }
    else
    {
        printf("Failed! errno = %d\n", errno);
    }
}

int main(int argc, char *argv[])
{
    pthread_t t1;
    thread_data data;

    data.name = "/thread1";
    data.id = mq_open(data.name, O_RDWR | O_CREAT, 0600, &attr);

    printf("Sending message %p (size %ld bytes)\n", &data, sizeof(char*));
    mq_send(data.id, (char*)&data, sizeof(char*), 0);
    printf("Message sent (queue %d).\n", data.id);

    pthread_create(&t1, NULL, new_thread, &data.id);
    pthread_join(t1, NULL);

    return 0;
}

输出如下所示:

$ ./a.out
Sending message 0x7ffd1c63eb20 (size 8 bytes)
Message sent (queue 3).
Waiting to receive message (queue 3)...
Message received in 0x7f5a92279700:

我希望这里有人能解释为什么会发生这种情况,因为我已经花了相当长的时间在这上面。

gmxoilav

gmxoilav1#

您的代码中没有正确的间接级别,无论是在发送还是接收部分。
您的mq_send()调用将发送您试图发送其指针的结构的内容的前8个字节。您的mq_receive()调用试图将数据存储在未初始化的指针中。
要修复发送部分:

thread_data data;
    thread_data* ptr = &data;

    /* ... code ... */
    mq_send(data.id, (char*)&ptr, sizeof(thread_data*), 0);
    /* ... other code ... */

注意这里的&ptr--您试图发送值ptr(它本身是一个指针,但在这里并不重要),这意味着您必须将指向该值的指针传递给mq_send
在receive部分,您必须将其更改为:

/* drop the pArg stuff */
    res = mq_receive(*(mqd_t*)arg, (char*)&pData, sizeof(thread_data*), NULL);
    if (res == sizeof(thread_data*)) {
        /* print pData-> ... */
    } else {
        /* error handling */
    }

同样,你想在这里接收值pData,所以你必须传递一个指向该值的指针给mq_receive,不要直接指定指针,那只意味着访问未初始化的内存。
为了更清楚地说明这一点,假设你想发送一个整数,那么你需要下面的代码:

/* plus initialize the queue with sizeof(int) */
int x = 42;
mq_send(data.id, (char*)&x, sizeof(int), 0);
/* and in the receive part */
int y = 0;
res = mq_receive(*(mqd_t*)arg, (char*)&y, sizeof(int), NULL);

因为你想发送一个指针而不是一个整数,所以改变的是传递给mq函数的变量类型和大小--但是在这两种情况下,你都把(char*)&variable传递给mq方法,变量是保存整数还是指针并不重要。

相关问题