IPC 队列 msgsnd 错误

Posted

技术标签:

【中文标题】IPC 队列 msgsnd 错误【英文标题】:IPC Queue msgsnd error 【发布时间】:2016-11-02 17:07:22 【问题描述】:

这是一个将 msg 发送到队列的简单程序,但它会给出“snd error”作为输出。 队列被创建。我检查了 ipcs -q。 我做错了什么?

#include<stdio.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/types.h>
#include<stdlib.h>
struct msg
int mtype;
char mtext[1024];

snd;
void main()

int id;
if(id=msgget(1234,IPC_CREAT|0666)<0)

    printf("ipc error");

else
    snd.mtype=1;
    scanf("%[^\n]",snd.mtext);
    getchar();

    if(msgsnd(id,&snd,sizeof(snd.mtext),IPC_NOWAIT)<0)
            printf("snd error");
    
    else 
        printf("msg snd");
    




【问题讨论】:

你为什么先scanf然后getchar()?考虑使用 fgets 吗? 但我猜这应该不是问题。我尝试在simplestcodings.blogspot.in/2010/08/… 处复制粘贴并运行代码,这可以正常工作。但是我的程序不起作用? 【参考方案1】:

我做错了什么?

您检查msgsnd 的返回码,这很好,这意味着您已经领先于许多程序员。但是您还没有阅读msgsnd 的完整手册,其中指出

返回值 失败时,两个函数都返回 -1,errno 表示错误,

其中errno 是重要部分。

进一步看,还有一个名为 ERRORS 的部分,它显示了可能出现的问题

错误 当 msgsnd() 失败时,errno 将被设置为以下之一 价值观:

  EACCES The calling process does not have write permission on the
          message queue, and does not have the CAP_IPC_OWNER capability.  

  EAGAIN The message can't be sent due to the msg_qbytes limit for the
          queue and IPC_NOWAIT was specified in msgflg.

...

再往下,你会发现一个示例部分

示例

  The program below demonstrates the use of msgsnd() and msgrcv().  

...

msgsnd的用法说明了一个重要的成语:当发生错误并且在errno中报告具体错误时,perror可能会打印此错误

if (msgsnd(qid, (void *) &msg, sizeof(msg.mtext),
           IPC_NOWAIT) == -1) 
    perror("msgsnd error");
    exit(EXIT_FAILURE);

perror 将显示一条消息,详细说明调用 msgsnd 时出现的问题。这也可以与任何其他系统调用一起使用。


根据手册“无效参数”(EINVAL)表示其中之一

EINVAL msqid 无效,或 msgsz 小于 0。 EINVAL(自 Linux 3.14 起)msgflg 指定了 MSG_COPY,但没有指定 IPC_NOWAIT。 EINVAL(自 Linux 3.14 起)msgflg 指定了 MSG_COPY 和 MSG_EXCEPT。

由于你没有指定MSG_COPY,所以错误一定是第一个。

msgsz 肯定大于 0 所以肯定是无效的msqid!

当你看时

if(id = msgget(1234, IPC_CREAT | 0666) < 0)

您会看到(id = msgget(...)) 周围缺少括号。最有可能msgget 返回的值 > 0,所以msgget(...) &lt; 0 为假,id 将变为 0(假),并采用 else 分支。

因此,调用msgsnd(0, ...) 很可能是错误的罪魁祸首和根源。


要解决这个问题,请明确

id = msgget(1234, IPC_CREAT | 0666);
if (id < 0) 
...
 else 
...

或至少在作业周围加上括号

if ((id = msgget(1234, IPC_CREAT | 0666)) < 0) 

【讨论】:

它说“无效参数”。我搜索了解决方案,但我没有那种问题。就像我的尺寸很好...我输入的消息小于 1024。我的 mtype = 1 这是正数。而且 sizeof(snd.mtext) 也没有错。现在有什么问题? 我面临的问题是当我尝试运行一个类似的程序时它可以工作。但这个程序不起作用。这个程序在我运行simplestcodings.blogspot.in/2010/08/… 时运行良好,而我自己编写的另一个程序也在运行。为什么不是这个?

以上是关于IPC 队列 msgsnd 错误的主要内容,如果未能解决你的问题,请参考以下文章

IPC消息队列如何发送对向量

Linux环境下 消息队列编程 碰到些问题 msgsnd发送10个数据,msgrcv只能接受9个,第一个接受不到

IPC 队列:- 接收错误数据

从消息队列接收

消息队列函数(msggetmsgctlmsgsndmsgrcv)

与 IPC 相关的 Xcode 错误