兼容性
select() 和 poll() 相對于 信號驅(qū)動和epoll() 在不同os之間的可移植性更高, 但是當(dāng)fd過多的時候, 效率也遠(yuǎn)低于后兩者.
觸發(fā)方式
- poll 和 select 只支持 水平觸發(fā)
- 信號驅(qū)動只支持邊緣觸發(fā)
- epoll支持水平觸發(fā)和邊緣觸發(fā)
select
- select返回的是含有整個句柄的數(shù)組莺奸,select 返回后, 程序并不知道是哪些 fd 準(zhǔn)備就緒, 而只知道一共有多少個就緒了, 需要進(jìn)程自己對傳遞過去的集合進(jìn)行遍歷和判斷
- select的觸發(fā)方式是水平觸發(fā)丑孩,應(yīng)用程序如果沒有完成對一個已經(jīng)就緒的文件描述符進(jìn)行IO操作,那么之后每次select調(diào)用還是會將這些文件描述符通知進(jìn)程
- 內(nèi)核 / 用戶空間內(nèi)存拷貝問題灭贷,select每次都會改變內(nèi)核中的句柄數(shù)據(jù)結(jié)構(gòu)集温学,因而每次select調(diào)用時都需要從用戶空間向內(nèi)核空間復(fù)制所有的句柄數(shù)據(jù)結(jié)構(gòu),產(chǎn)生巨大的開銷
- 單個進(jìn)程能夠監(jiān)視的文件描述符的數(shù)量存在最大限制甚疟,通常是1024仗岖,當(dāng)然可以更改數(shù)量
poll
- 每個fd都有屬于自身的 pollfd 結(jié)構(gòu), 它將 感興趣事件和觸發(fā)的事件分成了 events 和 revents. events 的值告訴內(nèi)核我們關(guān)心的是描述符的哪些事件 ; 當(dāng)某個 fd 有事件觸發(fā)了之后, 就由內(nèi)核修改 revents 的數(shù)據(jù), 互不干擾, 所以不必像 select 那樣, 每次調(diào)用都必須重置 fd 集合.
- 數(shù)組大小沒有限制
- 跟 select() 一樣, poll返回后, 程序并不知道是哪些 fd 準(zhǔn)備就緒, 而只知道一共有多少個就緒了, 需要進(jìn)程自己對傳遞過去的集合進(jìn)行遍歷和判斷
信號驅(qū)動
- 不需要由用戶進(jìn)程復(fù)制fd數(shù)組到內(nèi)核
- 信號處理不好可能會導(dǎo)致進(jìn)程出問題.
epoll
- epoll 支持水平觸發(fā)和邊緣觸發(fā). epoll 的機(jī)制類似于信號驅(qū)動, 都是進(jìn)程告訴內(nèi)核對哪些 fd 感興趣, 然后對應(yīng)的fd上有事件的時候, 由內(nèi)核主動通知進(jìn)程, 進(jìn)程再進(jìn)行相應(yīng)的處理.
- 可以避免復(fù)雜的信號處理流程(比如信號隊列溢出時的處理)
- 靈活性高, 可以指定我們希望檢查的事件類型(例如檢查 socket 的讀就緒事件、寫就緒事件览妖、或者兩者都檢查)
總結(jié)
select適合少量活躍連接轧拄,一般幾千。兼容平臺多讽膏。
epoll適合大量不太活躍的連接檩电。