2016-10-28 31 views
1

我正在從設備/文件描述符以阻塞的方式讀取數據。 可能會發生這種情況,即在另一個線程中設備關閉,filedescriptor被刪除。不幸的是,閱讀不會返回或注意並繼續阻止。C:如果filedescriptor被刪除,阻塞讀應該返回

作爲解決方法,我可以做一個while循環select作爲超時。如果發生超時,我可以檢查文件描述符,以防萬一它沒有調用read但返回。

我在想,如果在Linux-C中有更好的方法?

+0

「*我可以檢查filedescriptor *」檢查一下,請問? – alk

+0

「* ...和filedescriptor被刪除*」文件描述符如何被「*刪除*」? – alk

+0

@MarekKlein:如果文件描述符已經被傳遞給'close()',並且在另一個線程的平均時間內沒有被「回收」,則讀取將失敗並返回-1,這不一定需要等於' EOF'。 – alk

回答

2

你所描述的代碼具有內在的競爭條件 - 如果另一個線程可以在文件描述符,當你close()該文件描述符,其他線程也可以同樣是正準備打電話給read()而不是阻塞read()可以了。

除非您知道所有其他線程不再處於使用該文件描述符的位置,否則不能調用close()

處理像你所描述的情況的最簡單的方法是將一個線程作爲每個文件描述符的「擁有」線程,負責關閉文件描述符。其他線程不會直接關閉它 - 而是在某些共享數據結構中將文件描述符標記爲「要關閉」並喚醒擁有的線程。

可以使人們有可能通過在read()它不會阻止,但在select()poll(),而不是阻止另一個文件描述符喚醒線程擁有 - 通常一個管道 - 中集以及目標文件描述符。該線程通過寫入該管道的另一端而被喚醒。

+0

我的確有類似的東西。一個主線程,打開設備,分配內存...,並在同一個關閉函數中被調用,一旦處理完成。但是你是對的,而不是關閉並終止另一個線程中的讀取,我應該首先終止讀取並關閉filedescriptor。所有這些都可以像最初描述的那樣工作(while循環,檢查這個變量,select,read)。我認爲這是你的意思? – Arno

+0

@ user3392481:是的,但是如果正在讀取文件描述符的線程也是一個負責關閉它的人,那麼一旦它看到該標誌被設置(否則,您需要額外的同步以確保喚醒的線程已經喚醒並用文件描述符結束 - 就像通過互斥鎖和條件變量保護的引用計數一樣)。 – caf

2

一旦一個文件描述符被其他線程關閉,就不容易驗證它發生了。如果其他線程重新打開一個文件並得到相同的文件描述符?在成功調用close()時,不能再次訪問文件描述符,它將是undefined。在失敗的close()調用中,POSIX保留文件描述符unspecified的狀態。

select()選項存在與上述相同的情況。

在多線程程序中,您的問題與其他任何data race問題沒有什麼不同。我建議你重寫 的代碼,這樣線程就不會在沒有同步的情況下訪問文件描述符。或者,如果可能的話,避免從同一文件描述符讀取多個線程。

+0

哦,這是分開的。這只是在應用程序的結尾,你想確保關閉所有的線程,這個閱讀不會放棄。 – Arno

相關問題