msgrcv没有等待具有errno 22(EINVAL)的特定消息类型的消息

时间:2018-03-11 02:01:08

标签: c++ message-queue system-calls

我正在尝试在标准C库中使用msgsnd和msgrcv系统调用,但是没有达到预期/期望的性能。

我的问题是,当我调用msgrcv时,它不会等待具有指定mtype(4)的消息。

我首先发送一个mtype为1的消息。想法是另一个进程然后会收到此消息并发回一个mtype为4的确认消息。从documentation,我希望&# 34;如果msgtyp大于零,则收到msgtyp类型的第一条消息"。
我还希望它等到消息类型为msgtyp的消息在队列中。 来自文档:

  • 如果msgflg参数中未设置IPC_NOWAIT标志,则调用线程将暂停处理,直到出现以下情况之一:
    • 将所需类型的消息发送到消息队列。
    • 从系统中删除消息队列标识符msqid。发生这种情况时,msgrcv()函数返回的返回值为-1,errno设置为EIDRM。
    • 将信号传递给调用线程。发生这种情况时,msgrcv()函数返回,返回值为-1,errno设置为EINTR。

我的msgrcv函数不会等待。我在下面创建了一个最小,完整且可验证的示例。

(另请注意,我没有运行任何其他可能使用mtype = 1拦截此消息的伴随程序,并在测试此程序时发回另一条mtype = 4的消息)。

#include <sys/msg.h>
#include <iostream>
using namespace std;

int main() {
    int qid = msgget(ftok(".",'u'), IPC_EXCL|IPC_CREAT|0600);
    struct buf {
        long mtype; // required
        int message; // mesg content
    };
    buf msg;
    int size = sizeof(msg)-sizeof(long);

    msg.mtype = 1;
    msgsnd(qid, (struct msgbuf *)&msg, size, 0); // sending
    cout << msg.message << endl;
    //Get acknowledgement from receiverA
    msgrcv(qid, (struct msgbuf *)&msg, size, 4, 0); // read mesg
    cout << msg.message << endl;
}

更新:

msgrcv函数返回的errno值为22(EINVAL),根据文档的含义&#34; MessageQueueID参数不是有效的消息队列标识符。&#34;

所以我继续检查我的msgget函数的errno值是什么。 msgget函数返回值17(EEX​​IST)。不知道如何处理这个但是msgget()的文档说,&#34;如果msgflg同时指定了IPC_CREAT和IPC_EXCL并且密钥已存在消息队列,那么msgget()将失败并且errno设置为EEXIST。&#34 ;

只是搞乱了msgget函数,如果我改变了第二个参数,在ftok函数中生成一个不同的标识符,它只能在我运行一次时运行,如果我尝试再运行它第二次相同的标识符,错误返回。 所以我想我的问题可以简化为:我如何获得我想要使用的消息队列的qid但是如果它已经存在则不尝试生成它?

2 个答案:

答案 0 :(得分:1)

尝试在调用IPC_EXCL时删除msgget

来自https://www.tldp.org/LDP/lpg/node34.html

  

<强> IPC_EXCL

     

IPC_CREAT 一起使用时,如果队列已存在则失败。

答案 1 :(得分:1)

从手册页:

  

如果msgflg同时指定了IPC_CREAT和IPC_EXCL以及消息队列          已经存在key,然后msgget()失败,并将errno设置为EEXIST。

当我第一次尝试执行你的代码时,它在msgrcv()上被阻止,但是当我重新执行它时,它并没有。因为在下一次迭代中,msgget()失败了,EXIST和qid填充了-1。由于这个msgsnd()以及msgrcv()因无效参数而失败。

上述问题的解决方法是删除消息队列,在从测试程序返回之前使用msgctl()删除消息队列id,如下所示:

  

msgctl(qid,IPC_RMID,NULL);

建议:始终检查系统调用的返回值。

希望这会对你有所帮助。