我在 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;
}
uj5u.com熱心網友回復:
我在 process_B 的主執行緒的清理中有這個呼叫,它在 IPC 訊息佇列上接收訊息:
if (msgctl(qId, IPC_RMID, NULL) < 0) { perror("msgctl"); }到達時,報告以下內容:
msgctl : Invalid argument Error: failed to remove message queue.
“錯誤:”訊息必須來自其他一些不存在的代碼,但“msgctl:”訊息似乎是從 輸出的perror(),報告EINVAL. 對于IPC_RMID命令,這表明傳遞給函式的佇列 ID 無效。也許那個佇列已經被洗掉了?
我不清楚洗掉訊息佇列如何喚醒所有讀者和作者。在 process_B 洗掉訊息佇列之前,process_A 是否也必須以某種方式關閉?
移除佇列會喚醒所有等待的讀者和作者。也就是說,那些當前被阻止的嘗試向佇列發送訊息或從佇列接收訊息。檔案只是說這些呼叫將停止阻塞,而是失敗(回傳 -1)并errno設定為EIDRM。所以不,在 process_B 可以洗掉佇列之前,process_A 不必終止或執行任何其他操作。
然而,
如果 process_B 關閉,我會嘗試清理資源以包含此訊息佇列。
到目前為止還好。
如果它重新啟動,我希望 process_B 在清除佇列后“重新連接”到訊息佇列,以防 process_A 從未關閉。
我認為您沒有理解洗掉佇列意味著什么。成功洗掉它后,沒有任何東西可以重新連接。您必須改為創建一個新佇列,并以某種方式讓所有涉及的行程附加到并使用該佇列。它很可能具有不同的佇列 ID(盡管通過相同的密鑰獲得)。
是否可以清除佇列?然后當然我會對 process_A 做同樣的事情。
您可以通過阻止所有行程發送新訊息(通過行程共享互斥或信號量)然后接收所有可用訊息來清除佇列而不洗掉它。不要忘記提供要釋放的互斥鎖/信號量。
但是,我敦促您在此處考慮您的策略。如果您只是簡單地清除佇列而不洗掉它,那么在沒有 process_B 運行時,沒有什么可以阻止 process_A 向佇列發送更多訊息,所以
- 清除佇列實際上對資源使用沒有多大作用,并且
- 您需要考慮一個新的 process_B 在它開始執行之前將如何處理發送的訊息。
類似的適用于相反的方向。
另外,請記住 System V 訊息佇列具有內核持久性,因此它們的生命周期與任何特定行程的生命周期無關。SysV MQ 從創建到顯式洗掉,或直到系統關閉,以先到者為準。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/327461.html
