【问题标题】:why does msgrcv() sets msqid to 0?为什么 msgrcv() 将 msqid 设置为 0?
【发布时间】:2019-04-13 14:35:11
【问题描述】:

我有一个 c 程序,它应该通过 msgq 发送和接收 ipc 消息。

我遇到的问题是,当我运行 msgrcv() 时,它会将我的全局 int msqid 设置为 0。当然,我在其他方法中也需要它,例如在信号处理程序中。

这里有一些代码:

/* all the includes and some variables*/
#include "msg.h" // include the one I made
int msgQ; // global int

int main(int argc, char *argv[])
{
    key = ftok("progfile", 65);
    msgQ = msgget(key, 0666 | IPC_CREAT);
    printf("msg queue id: %d \n", msgQ);

    start_tik_tok(); // setting up the timer and the signal handler
    /* irrelevant code */

    void read_msgs(msgQ);
}

void read_msgs(int msgQid)
{
    while (1)
    {
        printf("before the read local:%d goval:%d\n", msgQid, msgQ);
        int ret = msgrcv(msgQid, &message, sizeof(message), 1, 0);
        printf("after the read local:%d global :%d\n", msgQid, msgQ);
        if (ret == -1)
            /* error handling */

        switch (message.action_type)
        {
            /* mesage handling */
        }
}

void signal_handler(int signo)
{
    /*I need the global int here to send some messages */
}

void start_tik_tok()
{
    //timer interval for setitimer function
    struct itimerval timer;
    timer.it_interval.tv_sec = 1; //every 1 seconds
    timer.it_interval.tv_usec = 0;
    timer.it_value.tv_sec = 1; //start in 1 seconds
    timer.it_value.tv_usec = 0;

    //action for the signal
    struct sigaction new_sa;
    memset(&new_sa, 0, sizeof(new_sa));
    new_sa.sa_handler = &signal_handler;

    sigaction(SIGALRM, &new_sa, NULL);
    setitimer(ITIMER_REAL, &timer, NULL);
}

msg.h 文件:

#include <sys/msg.h>

struct msg_buff{
    long mesg_type; //reciver
    int sender; //sender
    char action_type;
    char time_tiks; //time in tiks
} message;

输出:

消息队列ID:45416448

在读之前local:45416448 global:45416448

读取后local:45416448 global:0

...

您可以看到,在我运行msgrcv() 之后,msgQ 的值变为 0,即使我使用变量将值传递给方法 read_msgs()

【问题讨论】:

  • 不要发布带有省略与您的问题相关的任何内容的虚假代码的问题。 message 是什么?它在哪里声明?你在用 cmets 省略的所有代码中做了什么?
  • 好的,让我添加它;)
  • 也许该名称已被库使用,您应该使用其他名称,但这不太可能。你说你也在信号处理程序中使用msgQ?信号处理程序不是将其设置为 0 吗?请记住,信号会中断您的代码,如果它在 msgrcv() 调用中被中断,那么预计 msgQ 将在一个 printf() 和另一个之间切换。
  • 在附加说明中,由信号处理程序修改的全局变量应为volatile

标签: c message-queue


【解决方案1】:

msgrcv 函数接受一个指向结构的指针,该结构以long 类型的“标头”开头,后跟消息数据。 msgrcv 的第三个参数msgsz 是消息数据主体的大小,不包括作为标头的long。所以你应该传递类似sizeof message - sizeof(long) 的东西。通过传递sizeof message,您要求它溢出缓冲区sizeof(long) 字节,这正在破坏其他一些全局变量。

【讨论】:

  • 如果我这样做,我会得到error 7: Argument list too long
  • @JavierFuentes int ret = msgrcv(msgQid, &amp;message, sizeof(message) - sizeof(long), 1, 0);
  • 是的,使用命令ipcs -q 我可以看到每条消息都是 16 字节长,就像sizeof(message) retunr 值一样。但如果我这样做sizeof(message) - sizeof(long) 我得到 8,这使得 'msgrcv' 返回 errno 7(参数列表太长)
  • @JavierFuentes:你的发送端可能有相应的错误。
【解决方案2】:

我找到了解决方案,我不知道为什么,但它解决了。

我只是从一开始就初始化了 int。

改变了:

int msgQ; // global int

为:

int msgQ = 0; // global int

【讨论】:

    猜你喜欢
    • 2014-12-22
    • 1970-01-01
    • 2015-09-12
    • 1970-01-01
    • 1970-01-01
    • 2021-02-02
    • 2020-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多