是否可以通过 IPC 消息传递队列发送信号?

Posted

技术标签:

【中文标题】是否可以通过 IPC 消息传递队列发送信号?【英文标题】:Is it possible to send signals through IPC Message Passing Queue? 【发布时间】:2018-12-25 23:24:55 【问题描述】:

我尝试从进程 A 向进程 B 调用 kill 并且进程 B 已成功对信号作出反应。问题是我不想直接从 kill 函数发送信号,原因有两个:

1) 有时进程 A 可能没有权限,例如。进程 B 由另一个用户运行

2) 我希望能够通过消息队列从 A 向 B 发送信号

我正在创建一个消息队列,我从中发送以下结构的“对象”

typedef struct msg 
    long message_type;
    char message_text[SIZE];
message;

我想知道进程 A 是否可以通过 IPC 消息传递向 B 发出信号。我知道我可以通过将信号类型从进程 A 发送到 message_text 到 B 来实现这一点,然后在进程 B 中检查信号的类型并正确执行,但我想知道是否还有其他方法。

这是否可以通过将 sigaction 对象作为消息传递来实现:

struct sigaction as;
//...
msgsnd(queue_id, &as, length, IPC_NOWAIT);
//...

我知道这是完全不可行的,但这是我想要实现的。谢谢

【问题讨论】:

在 Linux 上有两种类型的 IPC 消息队列。请参阅mq_overview。至于(1),如果您在用户开始运行之前为已安装的程序正确设置了有效的用户 ID,那真的不应该成为问题。 (2) 消息不是信号。但是关于消息,接收者可以轮询它们或者可以设置异步消息处理程序。它们还具有需要处理的权限,类似于信号。还有命名管道和套接字可用于发送数据。 @Fred 那么是否有可能在进程 B 中有一个特殊的线程,它保持在一个循环中并不断检查“信号消息”,然后轮询正确的信号处理程序。线程能否正常反应,例如中断主线程,或完全关闭它? 【参考方案1】:

根据您的 cmets,您似乎希望 B 能够接收消息,但是当它收到“信号”消息时,它需要像收到常规信号一样行事。您提到 B 需要对来自“信号”消息的SIGTERMSIGINT 做出反应。

实现这一点的方法取决于使用 POSIX 消息队列或 System V 消息队列。

无论哪种方式,您似乎都不想使用 B 的主线程对消息队列的轮询,因为这会增加响应“信号”消息的延迟。

因此,对于 POSIX 消息队列,您可以使用 mq_notify() 来运行线程或发出新消息已到达的信号。否则 B 可以使用线程(甚至fork())来轮询消息队列。

收到“信号”消息后,您有几个选择。 A)您可以在 B 中使用 killraise 向自身(或 fork 的父级)发送正确类型的信号,或者 B)只需调用一个执行您想要的函数(即之类的东西)。

进程 A 可以随时发送“信号”消息。但是您需要了解,如果您使用命名队列,它们是持久的。也就是说,A 甚至可以在 B 开始之前发送“信号”消息,然后当 B 开始时,该消息就在那里等待。根据消息队列的制作方式,它可以是 N 条消息深度并且队列中有较旧的消息。一种处理方法是让 B 在处理任何消息之前清空队列。

【讨论】:

【参考方案2】:

消息队列无法实现信号的功能。使用信号可以异步中断或终止进程,但是使用消息队列在接收进程检查消息或等待它并在接收到消息后退出时,它实际上会忽略该消息的其余执行路径(同步)。但是,可以通过线程来实现。

【讨论】:

【参考方案3】:

如果您使用的是 POSIX 消息队列(使用 mq_send/mq_receive),那么每次将消息发送到消息队列时,进程 B 都可以请求(使用 mq_notify)发送一个信号。但是,您的示例似乎使用了不支持任何类型通知的 SYSV 遗留消息队列 (msgsnd)。

【讨论】:

如果提供所需的功能,我愿意切换到 POSIX 消息队列。所以基本上每次我发送消息时,我都可以包含我选择的信号? 该信号不包含在消息中或由发送方指定——相反,接收方可以告诉内核每次将消息发送到特定消息队列时发送一个信号(任何人)。

以上是关于是否可以通过 IPC 消息传递队列发送信号?的主要内容,如果未能解决你的问题,请参考以下文章

进程通信——管道消息队列共享内存信号量

IPC System V 消息队列 - 发送一个数组块

进程间通信——XSI IPC之消息队列

通过 IPC 传递非 POD [普通旧数据类型]

Linux信号发送与作业控制

进程间通信(信号量共享内存和消息队列)