是否可以通过 IPC 消息传递队列发送信号?
Is it possible to send signals through IPC Message Passing Queue?
我尝试从进程 A 调用 kill 到进程 B,并且进程 B 已成功响应信号。问题是我不想直接从 kill 函数发送信号,原因有两个:
1)有时进程A可能没有权限,例如。进程 B 被另一个用户运行
2) 我希望能够通过消息队列将信号从 A 发送到 B
我正在创建一个消息队列,我从中发送 "objects" 以下结构
typedef struct msg {
long message_type;
char message_text[SIZE];
}message;
我想知道进程A是否可以通过IPC消息传递向B发信号。我知道我可以通过将信号类型从进程 A 发送到 message_text 来实现这一点,然后在进程 B 中检查信号类型并正确操作,但我想知道是否还有另一种方法。
这是否可以通过将 sigaction 对象作为消息传递来实现:
struct sigaction as;
//...
msgsnd(queue_id, &as, length, IPC_NOWAIT);
//...
我知道这是完全不可行的,但这是我正在努力实现的目标。谢谢
消息队列无法实现信号的功能。使用信号可以异步中断或终止进程,但是使用消息队列,当接收进程检查消息或等待它并在接收消息后退出时,它实际上将忽略该消息执行路径的其余部分(同步)。但是,可以用线程来实现。
如果您使用 POSIX 消息队列(使用 mq_send/mq_receive),那么进程 B 可以请求(使用 mq_notify)在每次发送消息时发送一个信号到消息队列。但是,您的示例似乎使用的是 SYSV 遗留消息队列 (msgsnd),它不支持任何类型的通知。
根据您的评论,您似乎希望 B 能够接收消息,但是当它收到 "signal" 消息时,它需要表现得像收到了常规信号一样。您提到 B 需要对 "signal" 消息中的 SIGTERM
或 SIGINT
做出反应。
实现此目的的方法取决于使用 POSIX 消息队列或 System V 消息队列。
无论哪种方式,您似乎都不想使用 B 的主线程对消息队列进行轮询,因为这会增加响应 "signal" 消息的延迟时间。
因此,对于 POSIX 消息队列,您可以使用 mq_notify()
到 运行 线程或发出新消息已到达的信号。不然B可以用一个线程(甚至fork()
)轮询消息队列
收到 "signal" 消息后,您有几个选择。 A) 您可以在 B 中使用 kill
或 raise
向自身发送正确类型的信号(或在 fork
的情况下向父级发送信号),或 B) 只需调用一个函数做你想做的事(那种事)。
进程 A 可以随时发送 "signal" 消息。但是您需要了解,如果您使用命名队列,它们是持久的。也就是说,A 甚至可以在 B 启动之前发送 "signal" 消息,然后当 B 启动时,该消息就在那里等待。根据消息队列的制作方式,它可以是 N 条消息深度并且队列中有较旧的消息。一种处理方法是让 B 在处理任何消息之前清空队列。
我尝试从进程 A 调用 kill 到进程 B,并且进程 B 已成功响应信号。问题是我不想直接从 kill 函数发送信号,原因有两个:
1)有时进程A可能没有权限,例如。进程 B 被另一个用户运行
2) 我希望能够通过消息队列将信号从 A 发送到 B
我正在创建一个消息队列,我从中发送 "objects" 以下结构
typedef struct msg {
long message_type;
char message_text[SIZE];
}message;
我想知道进程A是否可以通过IPC消息传递向B发信号。我知道我可以通过将信号类型从进程 A 发送到 message_text 来实现这一点,然后在进程 B 中检查信号类型并正确操作,但我想知道是否还有另一种方法。
这是否可以通过将 sigaction 对象作为消息传递来实现:
struct sigaction as;
//...
msgsnd(queue_id, &as, length, IPC_NOWAIT);
//...
我知道这是完全不可行的,但这是我正在努力实现的目标。谢谢
消息队列无法实现信号的功能。使用信号可以异步中断或终止进程,但是使用消息队列,当接收进程检查消息或等待它并在接收消息后退出时,它实际上将忽略该消息执行路径的其余部分(同步)。但是,可以用线程来实现。
如果您使用 POSIX 消息队列(使用 mq_send/mq_receive),那么进程 B 可以请求(使用 mq_notify)在每次发送消息时发送一个信号到消息队列。但是,您的示例似乎使用的是 SYSV 遗留消息队列 (msgsnd),它不支持任何类型的通知。
根据您的评论,您似乎希望 B 能够接收消息,但是当它收到 "signal" 消息时,它需要表现得像收到了常规信号一样。您提到 B 需要对 "signal" 消息中的 SIGTERM
或 SIGINT
做出反应。
实现此目的的方法取决于使用 POSIX 消息队列或 System V 消息队列。
无论哪种方式,您似乎都不想使用 B 的主线程对消息队列进行轮询,因为这会增加响应 "signal" 消息的延迟时间。
因此,对于 POSIX 消息队列,您可以使用 mq_notify()
到 运行 线程或发出新消息已到达的信号。不然B可以用一个线程(甚至fork()
)轮询消息队列
收到 "signal" 消息后,您有几个选择。 A) 您可以在 B 中使用 kill
或 raise
向自身发送正确类型的信号(或在 fork
的情况下向父级发送信号),或 B) 只需调用一个函数做你想做的事(那种事)。
进程 A 可以随时发送 "signal" 消息。但是您需要了解,如果您使用命名队列,它们是持久的。也就是说,A 甚至可以在 B 启动之前发送 "signal" 消息,然后当 B 启动时,该消息就在那里等待。根据消息队列的制作方式,它可以是 N 条消息深度并且队列中有较旧的消息。一种处理方法是让 B 在处理任何消息之前清空队列。