C 使用 IPC 消息队列的信号使用和处理

Posted

技术标签:

【中文标题】C 使用 IPC 消息队列的信号使用和处理【英文标题】:C Signal usage and process using IPC message queues 【发布时间】:2017-02-15 10:59:28 【问题描述】:

我有一个程序使用信号 (SIGUSR2) 来设置 catch 处理函数来处理高优先级传入消息。

程序在其主循环中使用 msgrcv() 从 IPC 消息队列接收传入消息。当 IPC 消息队列的消息发送者想要通知程序有高优先级的消息传入时,它会向进程发送 SIGUSR2 以使其停止处理任何可能正在处理的当前消息。

在信号捕获处理函数中我首先在入口处做:

信号(SIGUSR2,SIG_IGN);

忽略任何发生抢占的新信号。

然后代码处理抢占请求,它将当前正在处理的消息存储回队列、内务管理等,然后在从信号处理函数返回之前执行:

信号(SIGUSR2,sighandler_func);

问题:如果在一纳秒后接收到另一个闪存处理信号 发出上述信号调用,将进程重新调度到 信号处理函数又来了?即:如果主循环中的代码在哪里 它执行 sighold(SIGUSR2) 和 sigrelse(SIGUSR2) 来停止/启动 抢占信号的接收优先还是只是 上面的信号调用重新激活信号处理程序?

【问题讨论】:

我的Magic 8 Ball 说“回复朦胧,再试一次”。请发布a Minimal, Complete, and Verifiable Example - 最好使用实际代码。 简单地使用第二个队列来处理高优先级的消息似乎更容易,也很重要。 同意,但我在可以进行的更改范围内受到客户的限制。 另外,SysV IPC 消息队列已经支持优先消息。为什么不让一个线程阻塞高优先级的消息,让另一个线程处理低优先级的消息?我强烈怀疑您的信号处理代码过于复杂,可能会调用非异步信号安全函数 - 请注意 msgrcv() 和其他 SysV IPC 函数不是异步信号安全的,不应从信号处理程序中调用. Flash抢占的信号接收仅在消息发送期间启用(基本上是写系统调用) - 在IPC msgrcv调用期间不启用。 【参考方案1】:

您应该为此使用 sigaction:

struct sigaction act;
memset(&act, 0, sizeof(act);
act.sa_handler = sighandler_func;
sigaction(SIGUSR2, &act, NULL);

这样,信号处理程序会在信号阻塞的情况下自动调用,从而导致事件(在您的情况下为 SIGUSR2)。如果现在 SIGUSR2 在处理程序执行期间到达,它会被阻塞,直到信号处理程序返回。然后,(当信号解除阻塞时),立即再次调用信号处理程序。

但是,您必须处理这种情况,即多个SIGUSR2 在信号处理程序的一次执行期间正确到达,因为它只会在处理程序返回后一次被调用。

【讨论】:

是的,在即将发布的版本中,信号处理调用都是使用 sigaction 使用符合 POSIX 的调用进行的。

以上是关于C 使用 IPC 消息队列的信号使用和处理的主要内容,如果未能解决你的问题,请参考以下文章

进程间通信——消息队列

System V IPC 之消息队列

IPC消息队列溢出后果

又见消息队列

C IPC - 无法从队列接收消息

❲知多少❳IPC之消息队列