2015-07-20 76 views
1

我一直在試圖確定是否可以在管道客戶端的線程之間共享管道句柄(在Windows上)。我最初的想法是,我不能這樣做,因爲除非我同步線程,否則數據可能會在服務器上交錯顯示,從而導致問題。不過,我現在想知道PIPE_TYPE_MESSAGE和PIPE_READMODE_MESSAGE管道是否允許我有一個多線程管道客戶端共享一個管道句柄。有沒有人對此有過明確的答案?跨多線程管道客戶端共享管道句柄

我希望跨客戶端線程共享單個管道句柄的原因是爲了節省每次我想發送數據時打開管道的開銷。我不能輕鬆地緩存客戶端線程的管道句柄,因爲我沒有創建客戶端線程。

我已經包含了一個描述管道類型模式的代碼段https://msdn.microsoft.com/en-us/library/windows/desktop/aa365605(v=vs.85).aspx。我強調了讓我懷疑消息模式是否能夠完成我想要做的事情的部分。

...

類型模式

的管道的類型模式決定數據是如何寫入到一個名爲 管。數據可以通過命名管道以字節流 或消息流的形式傳輸。調用CreateNamedPipe創建 命名管道的實例時,管道服務器指定管道類型爲 。對於 管道的所有實例,類型模式必須相同。

要創建字節類型管道,請指定PIPE_TYPE_BYTE或使用默認值 值。數據以字節流的形式寫入管道,並且系統不會區分寫入不同的 寫入操作的字節。

要創建消息類型管道,請指定PIPE_TYPE_MESSAGE。 系統 將寫入每個寫操作的字節視爲 消息單元。系統始終對 消息類型管道執行寫入操作,就好像啓用了直寫模式一樣。

...

感謝, 尼克

回答

1

雙方的ReadFile和WriteFile WinAPI的功能線程安全。不像我之前寫的(抱歉),這個線程安全並不保證來自不同線程的併發寫入不會被交錯。換句話說,不保證在其他線程獲得寫入權限之前,首先開始寫入其數據的線程將完成。來自MSDN:

雖然單扇區寫入是原子化的,但多扇區寫入不保證是原子的,除非您使用的是事務(即創建的句柄是事務句柄;例如,一個使用CreateFileTransacted創建的句柄)。

這將表明可以使用事務操作進行原子寫入,但我對此上下文中的事務瞭解不多。

要兌換我自己,我會嘗試爲您的問題提出備用解決方案。你可以在你的客戶端有一個單獨的作者線程,該線程擁有對管道的獨佔寫入權限。所有其他線程將它們的消息推送到FIFO隊列,同時寫入器線程讀取隊列並通過管道發送數據。這比鎖定整個寫入操作更好,因爲入隊/出隊操作要快得多,並且線程不會長時間阻塞。

您可以以編寫器線程可以等待的方式實現隊列,並且只有在隊列中有消息時纔會喚醒。否則,編寫程序線程將會出現繁忙循環,這是一個討厭的解決方案。

+1

這聽起來像你說的,因爲WriteFile(),這是我的客戶端將使用,是線程安全的數據將不會交錯。這似乎是操作系統正在同步呼叫。那是對的嗎?因此,如果兩個線程使用相同的FILE句柄,選擇一個相似但略有不同的示例,並且它們每個都向該文件寫入一些字節緩衝區,則無論客戶端緩衝區是否大於OS,這些字節都不會交錯運行時庫緩衝區,因此必須將自己分塊成多個寫入? – nickdu

+0

我對我的粗心大意的回答表示歉意:(在閱讀你的評論後,我意識到我的錯誤是非常錯誤的,並且我更新了我的答案,請重新檢查我的答案。 – dbajgoric

+0

這回到我原來的問題。面向消息的管道給我的印象是*也許*操作系統正在做一些特殊的事情來確保管道內的每個寫緩衝區都是完整的,因此將處理我已經概述的場景 – nickdu