如何处理不同大小的 Linux 消息队列(POSIX 或 SysV)中的信号

How to handle signals in Linux Message Queues (POSIX or SysV) with different sizes?

本文关键字:队列 消息 信号 POSIX SysV Linux 何处理 处理      更新时间:2023-10-16

处理具有不同大小信号的 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 个字节就足够了。

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

抱歉,完全重写,我将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 字节的数组可能无法正常工作。