【问题标题】:Error "Bad address" when reading from message queue on Linux在 Linux 上从消息队列中读取时出现错误“错误地址”
【发布时间】:2012-05-26 20:43:52
【问题描述】:

当我需要使用 Linux 消息队列编写简单的时间服务器和客户端时,我有任务。服务器打开一个消息队列,客户端发送一个带有其 PID 的请求(类型为 1 的消息),服务器读取该消息并发送一条 PID 类型的消息(取自读取的消息)。我把所有的代码都放在下面,因为我不知道我在哪里犯了错误。我不是 Linux 编程专家。不知道我写的server是否正确。

服务器和客户端包含的文件(我需要这样写)。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <string.h>
#include <signal.h>

#define QUEUE 100
#define PERM_ALL 0777

typedef struct my_msgbuf {
    long mtype;
    int pid;
} ClientMessage;

typedef struct my_msgbuf2 {
    long mtype;
    struct tm time;
} TimeMessage;

服务器

int m_queue;

void cleanup(int signum) {
    if (msgctl(m_queue, IPC_RMID, NULL) == -1) {
        printf("Something happen on clean up\n");
        exit(1);
    }
    exit(signum);
}

int main() {
    ClientMessage pid_message;
    TimeMessage t;
    time_t clock;
    struct tm *cur_time;

    if ((m_queue = msgget(QUEUE, PERM_ALL | IPC_CREAT)) == -1) {
        printf("Can't create and open message queue\n");
        exit(1);
    }
    printf("created message queue = %d\n", m_queue);
    fflush(stdout);
    //t = malloc(sizeof(TimeMessage));
    signal(SIGINT, cleanup);

    while (1) {
        if (msgrcv(m_queue, &pid_message, sizeof(pid_message.pid), 1, 0) == -1) {
            break;
        } else {
            t.mtype = pid_message.pid;
            clock = time(NULL);
            cur_time = localtime(&clock);
            memcpy(&t.time, cur_time, sizeof(struct tm));
            msgsnd(m_queue, &t, sizeof(struct tm), 0);
        }
    }

    cleanup(0);
}

客户

int main() {
    int m_queue;
    TimeMessage *t;
    ClientMessage client;

    if ((m_queue = msgget(QUEUE, PERM_ALL)) == -1) {
        perror("Error in opening queue");
        exit(1);
    }

    client.mtype = 1;
    client.pid = getpid();

    while (1) {
        if (msgsnd(m_queue, &client, sizeof(client.pid), 0) == -1) {
            perror("Error sending to queue");
            exit(1);
        } else {
            if (msgrcv(m_queue, t, sizeof(struct tm), client.pid, 0) == -1) {
                perror("Error reading from queue");
                exit(1);
            }   
            printf("time: %d:%d:%d\n", t->time.tm_hour, t->time.tm_min, t->time.tm_sec);
        }
    }
    return 0;
}

两个程序都编译没有错误,但客户端返回“从队列读取错误”msgrcv 返回 -1。

【问题讨论】:

  • 建议:使用设置errno 的API 时(如您的情况下的消息队列API),使用perror or strerror 可能是个好主意
  • 谢谢@another.anon.coward 我想知道为什么示例使用 perror
  • 现在 msgrcv 返回“错误地址”
  • 这意味着“msgp(缓冲区)指向的地址不可访问。”,您似乎没有为t分配内存,尝试将TimeMessage *t更改为@987654330怎么样@ & 传递 &amp;t 而不是 t?
  • 另外你传入msgrcv的大小似乎不正确,将sizeof(struct tm)更改为sizeof t(假设你已将*t更改为t

标签: c linux unix message-queue


【解决方案1】:

添加perror 后,您似乎收到了错误说明"Bad Address" (EFAULT),这意味着“msgp 指向的地址(缓冲区) 不可访问”。从代码看来,TimeMessage *t 没有分配内存,因此您可以分配内存或将其更改为TimeMessage t 并将&amp;t 而不是t 传递给msgrcv。大小也应该是sizeof t(假设从*t 更改为t,或sizeof(TimeMessage)*t)而不是sizeof(struct tm)(显然你会相应地更改printf 语句)
希望这会有所帮助!

【讨论】:

  • 谢谢,我添加了t = malloc(sizeof(TimeMessage));,它可以工作了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-19
  • 2012-07-06
  • 2020-08-21
  • 2015-09-17
  • 1970-01-01
  • 2022-06-16
  • 2013-07-18
相关资源
最近更新 更多