我目前的程序正在通過zmq接收消息。一個線程不時醒來,並檢查最後收到的zmq。如何使用ZeroMQ喚醒線程
現在我想改進這個設置,並實際處理每一條消息,而不是最後一次醒來。另外,我希望我的線程能夠在有新的東西時喚醒。有什麼辦法可以讓zmq在我的線程中有新消息後立即強制我的線程喚醒。
我目前的程序正在通過zmq接收消息。一個線程不時醒來,並檢查最後收到的zmq。如何使用ZeroMQ喚醒線程
現在我想改進這個設置,並實際處理每一條消息,而不是最後一次醒來。另外,我希望我的線程能夠在有新的東西時喚醒。有什麼辦法可以讓zmq在我的線程中有新消息後立即強制我的線程喚醒。
正如你所提到的「此外,我希望我的線程剛剛醒來,當有新的東西。」 這可如果回調被分配給數據來實現接收,所以每當一個新的數據到達回調將被執行。
但是念叨zeromq並參考以下鏈接後:
Is it possible to add an event handling to ZeroMQ to act when data is received/sent?
Does ZeroMQ have a notification/callback event/message for when data arrives?
它看起來像截至目前,ZeroMQ不執行,將通知我們時,任何回調新數據收到。您可以通過在阻塞模式下使用zmq_recv來檢查新數據(但這並不意味着在新數據到來時會喚醒,它會一直阻塞,直到數據到來)。在上面的鏈接表示
一個可能的解決方案:
您可以使用信號,在ZMQ每當一個新的數據到達,將通知一起。使用信號處理程序/中斷處理程序的優點是,在新數據到達之前它們不會阻塞您的代碼(例如在阻塞模式下,如zmq_recv()
),而是信號處理程序會被喚醒並且只有在接收到特定信號時纔會執行。
類似SIGUSR1
/SIGUSR2
的信號可用作新數據到達的指示。當新數據到達時,將信號處理程序分配給SIGUSR1
以執行代碼。
要喚醒的過程,只要你有一個新的數據,那麼你就必須發送數據以及發送的信號,如:
zmq_send(...);
kill(pid, SIGUSR1); /* Send signal SIGUSR1 to the process
whose PID is specified
*/
接收過程接收信號SIGUSR1
和醒來執行其處理程序。在這個信號的處理程序中,您可以讀取數據並執行一些任務。現在,如果您發送一些新的數據以及SIGUSR1
信號,則只會再次執行此處理程序。
ZMQ是關於Actor模型編程的。這是一個反應堆。您使用zmq_poll()
等待一組套接字中的一個套接字準備好讀取。當你這樣做時,你從中讀取。
因此,您的程序變成了一個循環,在頂部您呼叫zmq_poll()
哪些塊(或超時),然後處理哪個套接字已準備好讀取,然後循環。
相反,回調屬於Proactor模型編程。你說前面會發生什麼(通過設置回電),然後無論發生什麼都會發生。
重要的是要記住的是,電抗器和攝真的,真的不要混用。永遠不要試圖將兩者融合在一起,如果你能夠幫助它,它將成爲無盡混亂的根源。要麼全力以赴,要麼全力以赴。這就是爲什麼ZeroMQ沒有回撥機制。
的兩種風格的不良混合就是爲什麼IPC運輸爲ZeroMQ不工作在Windows上的原因。 ZeroMQ的反應堆是zmq_poll()
。從根本上說,這依賴於提供反應堆的操作系統。在Linux上,這是select()
或epoll()
,這是* nix的標準,可以與任何文件描述符(網絡套接字,IPC管道,串行端口等)一起使用。
相比之下,Windows不提供通用反應器。它最接近的是select()
,它只適用於網絡套接字。要阻止Windows中的管道,請使用接聽回叫的呼叫。從根本上講,Windows是一個前攝系統,對此它沒有太多要做。這就是爲什麼像Boost.Asio
這樣的東西也是原子的原因 - 它可以在Windows上運行。
它是相對直截了當地合成上的反應器系統的頂部的前攝。你的反應器循環只是成爲一個事件調度器。
相比之下,在Windows上執行高效反應器的嘗試必須求助於輪詢線程。這就是cygwin所做的。它們的實現POSIX select()
爲每個文件描述符(它們只是Windows HANDLE的抽象)運行一個線程,每個線程都忙於輪詢它們的句柄,等待查看是否可以讀取數據。效率不高。
現在真的,真的很有趣的是,微軟現在已經走了,做了的Windows 10在Linux運行時這是一個系統調用級別執行(這樣完全不同的Cygwin的)。這確實支持epoll()
,select()
所需的系統調用,它可以用於管道,套接字等。我真正想知道的是他們是如何實現這一目標的?明信片上的答案,請...
偉大的答案,讚賞操作系統內部的更廣泛的角度和詳細程度。優秀的文字。祝你有很多明信片到達。 – user3666197
@ user3666197,不客氣。還沒有任何明信片...我正在考慮在Windows 10 Linux運行時上運行一些實驗,看看我能否看到一些彈出的線程。 – bazza
如何啓動線程前面,然後做對消息隊列'zmq_recv'讀阻塞,使線程睡眠,直到它接收到消息? –
謝謝您的建議。但是阻塞讀取的問題是我的線程會被封鎖。而且我無法承擔大部分時間我的線程被阻塞。 :) – Ryan