什么是 I/O 多路復用:
I/O 多路復用指的是可以通過某種機制母蛛,監(jiān)視多個文件描述符,一旦某個文件描述符準備就緒后,就能夠通知程序進行相關的讀寫操作端壳,目前 I/O 多路復用機制主要包含三種:select痊剖、poll韩玩、epoll
select:
select 函數監(jiān)視的文件描述符包含三類:writefds、readfds陆馁、exceptfds找颓,當調用 select 函數后,會有阻塞叮贩,直到有相關的文件描述符準備就緒击狮,select 函數返回,當返回后益老,可以通過遍歷 fdset 獲取相關的已經準備就緒的文件描述符
select 函數的本質是通過設置或者檢查存放 fd 標志位的數據結構進行下一次的處理彪蓬,select 機制包含有幾個缺點:
- 單個進程能打開的文件描述符有數量限制,由 FD_SETSIZE 控制捺萌,默認是 1024
- 掃描 socket 的時候档冬,采用的是線性掃描,也就是輪詢的方式,這樣的話效率比較低
- 需要維護一個用于保存大量 fd 的數據結構酷誓,這樣的話會使得在用戶態(tài)和內核空間之間傳遞該數據結構的時候增大復制的開銷
poll:
poll 和 select 在本質上沒有太大的差別披坏, poll 將用戶傳入的數組拷貝至內核空間,查詢每一個 fd 對應的設備狀態(tài)盐数,如果 fd 對應的設備狀態(tài)處于準備就緒刮萌,則會在設備等待列表中存入一項繼續(xù)遍歷,如果遍歷完所有 fd 后發(fā)現沒有處于準備就緒狀態(tài)的設備娘扩,那么會將當前進程掛起着茸,直到有相關設備處于準備就緒狀態(tài),再次被喚醒琐旁,等被喚醒后需要再次進行多次遍歷
poll 機制中沒有最大連接數的限制涮阔,因為它采用的是鏈表方式存儲,但是這樣做會有一些缺陷:
- 大量的 fd 的數組被整體復制于用戶空間和內核地址空間中灰殴,而不管這些復制是不是有意義
- poll 還有一個特點敬特,支持水平觸發(fā),如果 fd 被上報但是沒有被處理牺陶,那么下一次 poll 時會繼續(xù)上報這個 fd
epoll:
epoll 是 select 和 poll 的增強版本伟阔,epoll 相比較于 select 和 poll 更加的靈活,epoll 使用一個文件描述符管理多個文件描述符掰伸,將用戶關系的文件描述符的事件保存在一個內核的時間列表中皱炉,這樣在用戶空間和內核空間只需要復制一次
epoll:
epoll 支持水平觸發(fā)和邊緣觸發(fā),最大的優(yōu)點在于邊緣觸發(fā)狮鸭,它只會告訴進程剛剛變?yōu)闇蕚渚途w狀態(tài)的 fd合搅,并且只會通知一次,還有一個特點是歧蕉,它采用的是事件就緒的通知方式灾部,通過 epoll_ctl 注冊 fd,一旦 fd 準備就緒后惯退,內核會采用類似 callback 回調函數的機制激活 fd赌髓,然后 epoll_await 等待通知
epoll的優(yōu)點:
- 沒有最大并發(fā)連接數的限制,打開 fd 的上限遠高于 1024
- epoll 的效率高催跪,沒有采用輪詢的方式锁蠕,不會隨著 fd 的數目增加而降低效率,只有處于活躍狀態(tài)的 fd 才會調用 callback 函數叠荠,epoll 最大的特點就在于它只管活躍狀態(tài)的連接匿沛,和連接總數沒有關系扫责,這也是在實際網絡中 epoll 要比 poll 和 select 效率高的原因