如何close/clear一个IPC消息队列?
How to close/clear an IPC message queue?
我在 process_B 的主线程清理中有这个调用,它接收 IPC 消息队列上的消息:
if (msgctl(qId, IPC_RMID, NULL) < 0) {
perror("msgctl");
}
到达后,报告如下:
msgctl : Invalid argument
Error: failed to remove message queue.
我有另一个 process_A,它向 process_B 发送消息并且没有被关闭。
然后man msgctl
中有这个语句...
IPC_RMID
Immediately remove the message queue, awakening all waiting
reader and writer processes (with an error return and errno set
to EIDRM). The calling process must have appropriate privileges
or its effective user ID must be either that of the creator or
owner of the message queue. The third argument to msgctl() is
ignored in this case.
我不清楚删除消息队列如何唤醒所有读者和作者。在 process_B 可以删除消息队列之前 process_A 是否也必须以某种方式关闭?
如果 process_B 关闭,我正在尝试清理资源以包含此消息队列。如果它重新启动,我希望 process_B 在清除队列后“重新连接”到消息队列,以防 process_A 从未关闭。可以清除队列吗?然后我当然会为 process_A.
做同样的事情
更新:(加入消息队列的开启):
key_t key = ftok(".", 'm');
int qid = msgget(key, IPC_CREAT | 0644);
if (qid == -1) {
perror("msgget");
return -1;
}
I have this call in the cleanup of the main thread of process_B which
receives messages on an IPC message queue:
if (msgctl(qId, IPC_RMID, NULL) < 0) {
perror("msgctl");
}
And when reached, reports the following:
msgctl : Invalid argument
Error: failed to remove message queue.
“错误:”消息必须来自其他一些没有证据的代码,但“msgctl:”消息似乎是从 perror()
输出的,在 EINVAL
上报告。对于 IPC_RMID
命令,表示传递给函数的队列 ID 无效。也许那个队列已经被删除了?
I'm not clear on how removing the message queue awakens all readers and writers. Does process_A have to somehow close as well before process_B can remove the message queue?
删除队列会唤醒所有等待 的读者和作者。也就是说,那些当前被阻止尝试向队列发送消息或从中接收消息的人。文档只是说这些调用将停止阻塞,而是失败(返回 -1),errno
设置为 EIDRM
。所以不,process_A 在 process_B 可以删除队列之前不必终止或执行任何其他操作。
然而,
If process_B closes, I'm trying to cleanup the resources to include
this message queue.
到目前为止还不错。
And if it is restarted, I'd like for process_B to
"reconnect" to the message queue after having cleared the queue in the
case that process_A was never shutdown.
我认为您没有理解删除队列意味着什么。成功删除后,就没有什么可以重新连接的了。您必须改为创建一个新队列,并以某种方式让所有涉及的进程附加到并使用该队列。它很可能有不同的队列 ID(尽管是通过相同的密钥获得的)。
Is clearing the queue
possible? And then of course I'd do the same for process_A.
您可以通过阻止所有进程发送新消息(通过进程共享的互斥量或信号量)然后接收所有可用消息来清除队列而不删除它。不要忘记提供要释放的互斥量/信号量。
但是,我敦促您在这里考虑一下您的策略。如果您只是清除队列而不删除它,那么没有什么可以阻止 process_A 在没有 process_B 运行 的情况下向队列发送更多消息,所以
- 清除队列实际上对资源使用没有多大作用,并且
- 您需要考虑新的 process_B 将如何处理在开始执行之前发送的消息。
反向同样适用。
此外,请记住 System V 消息队列具有内核持久性,因此它们的生命周期与任何特定进程的生命周期无关。 SysV MQ 将从创建到显式删除,或者直到系统关闭,以先到者为准。
我在 process_B 的主线程清理中有这个调用,它接收 IPC 消息队列上的消息:
if (msgctl(qId, IPC_RMID, NULL) < 0) {
perror("msgctl");
}
到达后,报告如下:
msgctl : Invalid argument
Error: failed to remove message queue.
我有另一个 process_A,它向 process_B 发送消息并且没有被关闭。
然后man msgctl
中有这个语句...
IPC_RMID
Immediately remove the message queue, awakening all waiting
reader and writer processes (with an error return and errno set
to EIDRM). The calling process must have appropriate privileges
or its effective user ID must be either that of the creator or
owner of the message queue. The third argument to msgctl() is
ignored in this case.
我不清楚删除消息队列如何唤醒所有读者和作者。在 process_B 可以删除消息队列之前 process_A 是否也必须以某种方式关闭?
如果 process_B 关闭,我正在尝试清理资源以包含此消息队列。如果它重新启动,我希望 process_B 在清除队列后“重新连接”到消息队列,以防 process_A 从未关闭。可以清除队列吗?然后我当然会为 process_A.
做同样的事情更新:(加入消息队列的开启):
key_t key = ftok(".", 'm');
int qid = msgget(key, IPC_CREAT | 0644);
if (qid == -1) {
perror("msgget");
return -1;
}
I have this call in the cleanup of the main thread of process_B which receives messages on an IPC message queue:
if (msgctl(qId, IPC_RMID, NULL) < 0) { perror("msgctl"); }
And when reached, reports the following:
msgctl : Invalid argument Error: failed to remove message queue.
“错误:”消息必须来自其他一些没有证据的代码,但“msgctl:”消息似乎是从 perror()
输出的,在 EINVAL
上报告。对于 IPC_RMID
命令,表示传递给函数的队列 ID 无效。也许那个队列已经被删除了?
I'm not clear on how removing the message queue awakens all readers and writers. Does process_A have to somehow close as well before process_B can remove the message queue?
删除队列会唤醒所有等待 的读者和作者。也就是说,那些当前被阻止尝试向队列发送消息或从中接收消息的人。文档只是说这些调用将停止阻塞,而是失败(返回 -1),errno
设置为 EIDRM
。所以不,process_A 在 process_B 可以删除队列之前不必终止或执行任何其他操作。
然而,
If process_B closes, I'm trying to cleanup the resources to include this message queue.
到目前为止还不错。
And if it is restarted, I'd like for process_B to "reconnect" to the message queue after having cleared the queue in the case that process_A was never shutdown.
我认为您没有理解删除队列意味着什么。成功删除后,就没有什么可以重新连接的了。您必须改为创建一个新队列,并以某种方式让所有涉及的进程附加到并使用该队列。它很可能有不同的队列 ID(尽管是通过相同的密钥获得的)。
Is clearing the queue possible? And then of course I'd do the same for process_A.
您可以通过阻止所有进程发送新消息(通过进程共享的互斥量或信号量)然后接收所有可用消息来清除队列而不删除它。不要忘记提供要释放的互斥量/信号量。
但是,我敦促您在这里考虑一下您的策略。如果您只是清除队列而不删除它,那么没有什么可以阻止 process_A 在没有 process_B 运行 的情况下向队列发送更多消息,所以
- 清除队列实际上对资源使用没有多大作用,并且
- 您需要考虑新的 process_B 将如何处理在开始执行之前发送的消息。
反向同样适用。
此外,请记住 System V 消息队列具有内核持久性,因此它们的生命周期与任何特定进程的生命周期无关。 SysV MQ 将从创建到显式删除,或者直到系统关闭,以先到者为准。