多個線程如何操做同一個epoll fd

       本身之前作一個接口服務器時候,這種場景下個人設計是多個線程操做同一個epoll fd。彼時,個人理由是epoll的系列函數是線程安全的。 linux

       固然有人不理解爲何會有多個線程操做同一個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(就不該有這種行爲操做)。 app

       經過以上兩段man大神的神示,除了一個線程在epoll或者select中監控一個socket時候另一個線程對這個socket進行close這種狀況,我就能夠認爲多個線程操做同一個epoll fd的行爲是安全的,即我上面的操做是沒有問題的。 less

       以上是我的愚見,懇請你們批評指正。 socket

       另外嚴厲譴責諸如推酷「www.tuicool.com」這種垃圾抄襲網站不經本人容許就轉載本人blog的行爲。 ide

相關文章
相關標籤/搜索