詳解IO多路複用中的select, poll, epoll

select, poll, epoll 都是I/O多路複用的具體的實現,這三個是不同時期先後順序出來的,也是爲了改進性能。

I/O多路複用這個概念被提出來以後, select是第一個實現 (1983 左右在BSD裏面實現的)。

1.select 被實現以後,暴露出了很多問題。

  • select 會修改傳入的參數數組,這個對於一個需要調用很多次的函數,是非常不友好的。
  • select 如果任何一個sock(I/O stream)出現了數據,select 僅僅會返回,但是並不會告訴你是哪個sock上有數據,於是你只能自己一個一個的找,10幾個sock可能還好,要是幾萬的sock每次都找一遍,這就消耗了很多無謂開銷。
  • select 只能監視1024個鏈接, linux 定義在頭文件中的,參見FD_SETSIZE。
  • select 不是線程安全的,如果你把一個sock加入到select, 然後突然另外一個線程發現,這個sock不用,要收回。這時候這個select 不支持的,如果你強制關掉這個sock,結果不可預測的。

2.poll的誕生:於是14年以後(1997年)一幫人又實現了poll, poll 修復了select的很多問題,比如:

  • poll 去掉了1024個鏈接的限制,於是要多少鏈接呢, 自己隨意設置。
  • poll 從設計上來說,可以不再修改傳入數組,當然這個要看你的平臺了。

但是poll仍然不是線程安全的, 這就意味着,不管服務器有多強悍,你也只能在一個線程裏面處理一組I/O流。你當然可以拿多進程來配合了,不過就有了多進程的各種問題。

3.於是5年以後, 在2002, 大神 Davide Libenzi 實現了epoll

epoll 可以說是I/O 多路複用最新的一個實現,epoll 修復了poll 和select絕大部分問題, 比如:

  • epoll 現在是線程安全的。
  • epoll 現在不僅告訴你sock組裏面數據,還會告訴你具體哪個sock有數據,你不用自己去找了。

可是epoll 有個致命的缺點,就是隻有linux支持。比如BSD上面對應的實現是kqueue。

nginx就是使用的epoll

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章