1. 程式人生 > >多個執行緒如何操作同一個epoll fd

多個執行緒如何操作同一個epoll fd

自己以前做一個介面伺服器時候,這種場景下我的設計是多個執行緒操作同一個epoll fd。彼時,我的理由是epoll的系列函式是執行緒安全的。

       當然有人不理解為什麼會有多個執行緒操作同一個epoll fd的情形,這裡稍微鋪陳一下介面伺服器的場景。epoll fd有執行緒1維護,監聽服務端埠的socket的accept出來的acceptor(即新的socket fd)也放在這個epoll fd中。當收到客戶端連結請求時候,執行緒2從連線池connector pool中挑選出來一個connector,connector的作用是轉發請求,此時connector會把acceptor快取起來。如果connector收到回覆後,connector會通過acceptor向客戶端返回一些資料後,執行緒2此時需要把acceptor在add進epoll fd中。

      以前我以為epoll fd是多執行緒安全的,我就直接通過epoll_ctl(epoll fd,acceptor,add)把acceptor放進epoll fd中。

      現在再回首看看,自己是想當然的這樣操作了,沒有任何依據。孟子曰,“行有不得,反求諸己”。既然自己無法解開困惑,那就求助偉大的man了。通過“man epoll_wait”後,得到這麼一句話:

NOTES
     While one thread is blocked in a call to epoll_pwait(), it is possible for another thread to add a file descriptor to the waited-upon epoll instance.  If the new file descriptor becomes ready, it will cause the epoll_wait() call to unblock.
     For a discussion of what may happen if a file descriptor in an epoll instance being monitored by epoll_wait() is closed in another thread, see select(2).

       翻譯後就是:如果一個執行緒正阻塞在epoll_pwait上,此時可能有另外一個執行緒要把一個socket fd新增到這個epoll fd上,如果這個這個新的socket fd被新增進去後處於ready狀態,那麼epoll_wait就不會再處於阻塞狀態。如果由epoll fd監控的一個socket fd被另外一個執行緒close掉,此時系統處於何種狀態請參考select(2)。通過"man 2 select"後,得到如下一段話:   

   Multithreaded applications
       If a file descriptor being monitored by select() is closed in another thread, the result is unspecified.  On some UNIX systems, select() unblocks and returns, with an indication that the file descriptor is ready (a subsequent I/O operation will likely fail with an error, unless another the file descriptor reopened between the time select() returned  and the I/O operations was performed).  On Linux (and some other systems), closing the file descriptor in another thread has no effect on select().  In summary, any application that relies on a particular behavior in this scenario must be considered buggy.

       翻譯後,其意義為:如果一個執行緒中由select管理的socket被另外一個執行緒close掉,將會發生什麼只有天曉得。在一些UNIX系統中,select會結束阻塞態並返回,它會標識這個socket處於ready狀態(後面對這個socket的操作會失敗,os也會給出錯誤提示,除非在select返回和程序對這個socket進行讀寫這段時間段內,os又把同一個socket fd分配出去了)。在linux(和其他同類的系統)上,這種行為不會影響select(即有阻塞態變為非阻塞態)。總之,如果一個程式中這種行為應該被認為是一個bug(就不應有這種行為操作)。

       通過以上兩段man大神的神示,除了一個執行緒在epoll或者select中監控一個socket時候另外一個執行緒對這個socket進行close這種情況,我就可以認為多個執行緒操作同一個epoll fd的行為是安全的,即我上面的操作是沒有問題的。

       以上是個人愚見,懇請大家批評指正。

       另外嚴厲譴責諸如推酷“www.tuicool.com”這種垃圾抄襲網站不經本人允許就轉載本人blog的行為。

--------------------- 本文來自 企鵝 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/menggucaoyuan/article/details/38959725?utm_source=copy