在fd_set(對於select()或pselect())中使用結構複製是否有任何平臺導致問題?
select()
andpselect()
系統呼叫修改它們的引數(‘fd_set *’引數),因此輸入值告訴系統哪些檔案描述符要檢查,返回值告訴程式員哪個檔案描述符當前可用.
如果您要為同一組檔案描述符重複呼叫它們,則需要確保每個呼叫都有一個新的描述符副本.明確的方法是使用結構副本:
fd_set ref_set_rd; fd_set ref_set_wr; fd_set ref_set_er; ... ...code to set the reference fd_set_xx values... ... while (!done) { fd_set act_set_rd = ref_set_rd; fd_set act_set_wr = ref_set_wr; fd_set act_set_er = ref_set_er; int bits_set = select(max_fd, &act_set_rd, &act_set_wr, &act_set_er, &timeout); if (bits_set > 0) { ...process the output values of act_set_xx... } }
(編輯以刪除不正確的結構fd_set引用 – 由’R ..’指出)
我的問題:
>是否有任何平臺,如圖所示,做fd_set值的結構副本是不安全的?
我擔心有隱藏的記憶體分配或任何意想不到的內容. (存在巨集/功能FD_SET(),FD_CLR(),FD_ZERO()和FD_ISSET()以掩蓋應用程式中的內部.)
我可以看到MacOS X(達爾文)是安全的;因此,其他基於BSD的系統可能是安全的.您可以通過記錄您知道的其他系統在您的答案中是安全的幫助.
(我對fd_set可以用超過8192個開啟的檔案描述符的效果做出了很小的考慮 – 預設的開啟檔案的最大數量只有256,但是最大數量是’unlimited’,而且由於結構是1 KB,複製程式碼的效率並不高,但是通過一系列檔案描述符來重新建立每個週期的輸入掩碼也不一定也是有效的.也許你不能在你有很多檔案描述符開啟的時候做不到select那就是當你最有可能需要這個功能的時候.)
有一個相關的SO問題 – 詢問關於‘poll() vs select()’ 的問題,解決了這個問題的一組不同的問題.
請注意,在MacOS X上 – 並且大概BSD更普遍 – 有一個FD_COPY()巨集或函式,與有效的原型:
> extern void FD_COPY(const restrict fd_set * from,restrict fd_set * to);.
在尚不可用的平臺上可能值得模仿.
由於struct fd_set只是一個常規的C結構,所以應該總是很好.我個人不喜歡通過=運算子進行結構複製,因為我已經開發了大量的平臺,無法訪問正常的編譯器本體.在我的書中,使用memcpy()而不是使編譯器插入函式呼叫是一個更好的方法.
從C規範,6.5.16.1簡單賦值(為了簡潔起見,這裡編輯):
One of the following shall hold:
…
- the left operand has a qualified or unqualified version of a structure or union type compatible with the type of the right;
…
Insimple assignment (=), the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand.
If the value being stored in an object is read from another object that overlaps in any way the storage of the first object, then the overlap shall be exact and the two objects shall have qualified or unqualified versions of a compatible type; otherwise, the behavior is undefined.
所以你去,只要struct fd_set實際上是一個常規的C結構,你保證成功.然而,它確實依賴於您的編譯器發出某種型別的程式碼來執行,或者依賴於它用於結構分配的任何memcpy().如果您的平臺由於某種原因無法與編譯器的內部庫連結,則可能無法正常工作.
如果你有更多的開啟的檔案描述符,而不是適合struct fd_set,你將不得不發揮一些技巧. linuxman page 說:
Anfd_set
is a fixed size buffer. ExecutingFD_CLR()
orFD_SET()
with a value offd
that is negative or is equal to or larger thanFD_SETSIZE
will result in undefined behavior. Moreover, POSIX requiresfd
to be a valid file descriptor.
如下所述,證明您的程式碼在所有系統上都安全可能不值得.提供FD_COPY()僅用於這種使用,並且可能總是保證:
FD_COPY(&fdset_orig, &fdset_copy)
replaces an already allocated&fdset_copy
file descriptor set with a copy of&fdset_orig
.
程式碼日誌版權宣告:
翻譯自:http://stackoverflow.com/questions/2421672/are-there-any-platforms-where-using-structure-copy-on-an-fd-set-for-select-or