IO多路復用:I/O是指網絡I/O,多路指多個TCP連接(即socket或者channel),復用指復用一個或幾個線程。意思說一個或一組線程處理多個TCP連接。最大優勢是減少系統開銷小,不必創建過多的進程/線程,也不必維護這些進程/線程。
IO多路復用使用兩個系統調用(select/poll/epoll和recvfrom),blocking IO只調用了recvfrom;select/poll/epoll 核心是可以同時處理多個connection,而不是更快,所以連接數不高的話,性能不一定比多線程+阻塞IO好,多路復用模型中,每一個socket,設置為non-blocking,阻塞是被select這個函數block,而不是被socket阻塞的。
select機制
基本原理:
客戶端操作服務器時就會產生這三種文件描述符(簡稱fd):writefds(寫)、readfds(讀)、和exceptfds(異常)。select會阻塞住監視3類文件描述符,等有數據、可讀、可寫、出異常 或超時、就會返回;返回后通過遍歷fdset整個數組來找到就緒的描述符fd,然后進行對應的IO操作。
優點:
幾乎在所有的平台上支持,跨平台支持性好
缺點:
由於是采用輪詢方式全盤掃描,會隨着文件描述符FD數量增多而性能下降。
每次調用 select(),需要把 fd 集合從用戶態拷貝到內核態,並進行遍歷(消息傳遞都是從內核到用戶空間)
默認單個進程打開的FD有限制是1024個,可修改宏定義,但是效率仍然慢。
poll機制:
基本原理與select一致,也是輪詢+遍歷;唯一的區別就是poll沒有最大文件描述符限制(使用鏈表的方式存儲fd)。
epoll機制:
基本原理:
沒有fd個數限制,用戶態拷貝到內核態只需要一次,使用時間通知機制來觸發。通過epoll_ctl注冊fd,一旦fd就緒就會通過callback回調機制來激活對應fd,進行相關的io操作。
epoll之所以高性能是得益於它的三個函數
1)epoll_create()系統啟動時,在Linux內核里面申請一個B+樹結構文件系統,返回epoll對象,也是一個fd
2)epoll_ctl() 每新建一個連接,都通過該函數操作epoll對象,在這個對象里面修改添加刪除對應的鏈接fd, 綁定一個callback函數
3)epoll_wait() 輪訓所有的callback集合,並完成對應的IO操作
優點:
沒fd這個限制,所支持的FD上限是操作系統的最大文件句柄數,1G內存大概支持10萬個句柄
效率提高,使用回調通知而不是輪詢的方式,不會隨着FD數目的增加效率下降
內核和用戶空間mmap同一塊內存實現(mmap是一種內存映射文件的方法,即將一個文件或者其它對象映射到進程的地址空間)
例子:100萬個連接,里面有1萬個連接是活躍,我們可以對比 select、poll、epoll 的性能表現
select:不修改宏定義默認是1024,l則需要100w/1024=977個進程才可以支持 100萬連接,會使得CPU性能特別的差。
poll: 沒有最大文件描述符限制,100萬個鏈接則需要100w個fd,遍歷都響應不過來了,還有空間的拷貝消耗大量的資源。
epoll: 請求進來時就創建fd並綁定一個callback,主需要遍歷1w個活躍連接的callback即可,即高效又不用內存拷貝。