c++ - msgrcv 不等待带有错误号 22 (EINVAL) 的特定消息类型的消息

标签 c++ message-queue system-calls

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

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

我首先发送一条 mtype 为 1 的消息。我的想法是,另一个进程将收到此消息并发送回一条 mtype 为 4 的确认消息。来自 documentation ,我希望“如果 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),根据文档,这意味着“MessageQueueID 参数不是有效的消息队列标识符。”

所以我继续检查我的 msgget 函数的 errno 值是多少。 msgget 函数返回值 17 (EEXIST)。不知道该怎么办,但是 msgget() 的文档说“如果 msgflg 指定了 IPC_CREAT 和 IPC_EXCL,并且 key 的消息队列已经存在,则 msgget() 失败,errno 设置为 EEXIST。”

如果我在 ftok 函数中更改 2nd 参数以生成不同的标识符,只是因为弄乱了 msgget 函数,它就可以工作,但只有当我运行它一次时,如果我尝试使用相同的标识符,错误返回。 所以我想我的问题可以简化为:如何获取我想使用的消息队列的 qid,但如果它已经存在则不尝试生成它?

最佳答案

尝试在调用 msgget 时删除 IPC_EXCL

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

IPC_EXCL

When used with IPC_CREAT, fail if queue already exists.

关于c++ - msgrcv 不等待带有错误号 22 (EINVAL) 的特定消息类型的消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49215921/

相关文章:

linux - 使用 write syscall linux 的正确方法

c++ - linux上如何使用编程方式拦截正在运行的进程调用的系统调用?

c++ - 是否保证每个迭代器仅调用一次remove_if谓词?

c++ - x86 和 x64 堆栈帧

c++ - 使用基类对象来表示其派生类对象

java - 适用于 Java、PHP 和 Python 的开源队列

python - 服务器可以发布广播消息来终止工作人员吗?兔子MQ

c++ - pantheios 会捕获段错误吗?

apache-kafka - 设计 Kafka 主题 - 多主题 vs 一个大主题

c - C 中的写入和读取,套接字 AF_UNIX