【问题标题】:How to handle signals in Linux Message Queues (POSIX or SysV) with different sizes?如何处理不同大小的 Linux 消息队列(POSIX 或 SysV)中的信号?
【发布时间】:2015-02-15 09:19:08
【问题描述】:

处理具有不同大小信号的 Linux 消息队列(POSIX 或 SysV)的信号的最佳方法是什么?

假设我有一个进程可以接收两个或多个不同大小的不同信号。例如:

struct sig1 {
   long mType;
   char data[10];
};

struct sig2 {
   long mType;
   char data[20000];
};

现在,据我了解消息队列 API,为了接收这些信号,我需要确保我可以为数据提供一个缓冲区,该缓冲区至少等于消息队列中传递的最大消息的大小.

int msgrcv(int msqid, void *msgp, size_t msgsz,
           long msgtyp, int msgflg);

对我来说,需要为收到的每个信号分配一个与队列中传递的最大消息一样大的新缓冲区似乎是不切实际的。或者有什么方法可以在将消息从队列中取出之前轮询队列以了解消息的大小?现在,在我上面提供的极端情况下,我需要为每个接收到的信号分配 20000 个字节,即使接收到 sig1 时,只有 10 个字节就足够了。

假设我有一个信号负载高且信号大小差异很大的应用程序。有没有好办法处理这种情况?另外,从性能的角度来看,我是否会因为需要为每次接收分配更大的缓冲区而损失性能?

【问题讨论】:

    标签: c++ linux message-queue


    【解决方案1】:

    抱歉,完全重写,我将msgrcv 与从管道和套接字读取混淆了,其中每个数据包都可以部分或整体读取。

    您需要有一个足够大的接收缓冲区,以容纳您可能收到的最大消息。

    实际大小作为来自msgrcv的返回值返回,所以是这样的:

     struct sig2 msg;
     size_t n = msgrcv(queue_id, &msg, sizeof(msg.data), -1, 0);
     if (n == -1)
     {
        ... error - inspect errno to understand what went wrong ... 
     }
    

    还请注意,默认大小为 16384 字节,因此除非您重新配置默认消息大小,否则 20000 字节数组可能无法工作。

    【讨论】:

    • 现在您将如何读取 mType 和 size 字段(如果我们添加了这样的字段)?据我所知,这些消息队列没有可用的 peek 功能?执行 msgrcv 时,手册指出该消息已从队列中删除。而对于固定宽度的整数类型,现在根据linux.die.net/man/2/msgrcv mtype 实际上应该是 long 类型。由于它是特定于系统的,如果您在 32 位架构上运行,那么您希望它是 32 位的。 64 位架构也是如此。
    • @user2043377:完全重写了答案。来晚了,这是我的借口,我会坚持下去。
    猜你喜欢
    • 2019-03-17
    • 2011-01-22
    • 1970-01-01
    • 2013-04-16
    • 1970-01-01
    • 1970-01-01
    • 2020-03-05
    • 2014-09-04
    • 2016-11-26
    相关资源
    最近更新 更多