現(xiàn)在有這么一個場景:我是一個很忙的大老板,我有100個手機(jī),手機(jī)來信息了,我的秘書就會告訴我“老板,你的手機(jī)來信息了?!蔽液苌鷼?,我的秘書就是這樣子,每次手機(jī)來信息就只告訴我來信息了,老板趕緊去看。但是她從來不把話說清楚:到底是哪個手機(jī)來信息??!我可有100個手機(jī)??!于是,我只能一個一個手機(jī)去查看,來確定到底是哪幾個手機(jī)來信息了。這就是IO復(fù)用中select模型的缺點(diǎn)!老板心想,要是秘書能把來信息的手機(jī)直接拿到我桌子上就好了,那么我的效率肯定大增(這就是epoll模型)。
那我們先來總結(jié)一下select模型的缺點(diǎn):
單個進(jìn)程能夠監(jiān)視的文件描述符的數(shù)量存在最大限制,通常是1024,當(dāng)然可以更改數(shù)量,但由于select采用輪詢的方式掃描文件描述符,文件描述符數(shù)量越多,性能越差;(在linux內(nèi)核頭文件中,有這樣的定義:#define __FD_SETSIZE 1024)
內(nèi)核 / 用戶空間內(nèi)存拷貝問題,select需要復(fù)制大量的句柄數(shù)據(jù)結(jié)構(gòu),產(chǎn)生巨大的開銷;
select返回的是含有整個句柄的數(shù)組,應(yīng)用程序需要遍歷整個數(shù)組才能發(fā)現(xiàn)哪些句柄發(fā)生了事件;select的觸發(fā)方式是水平觸發(fā),應(yīng)用程序如果沒有完成對一個已經(jīng)就緒的文件描述符進(jìn)行IO操作,那么之后每次select調(diào)用還是會將這些文件描述符通知進(jìn)程。
設(shè)想一下如下場景:有100萬個客戶端同時與一個服務(wù)器進(jìn)程保持著TCP連接。而每一時刻,通常只有幾百上千個TCP連接是活躍的(事實(shí)上大部分場景都是這種情況)。如何實(shí)現(xiàn)這樣的高并發(fā)?
粗略計(jì)算一下,一個進(jìn)程最多有1024個文件描述符,那么我們需要開1000個進(jìn)程來處理100萬個客戶連接。如果我們使用select模型,這1000個進(jìn)程里某一段時間內(nèi)只有數(shù)個客戶連接需要數(shù)據(jù)的接收,那么我們就不得不輪詢1024個文件描述符以確定究竟是哪個客戶有數(shù)據(jù)可讀,想想如果1000個進(jìn)程都有類似的行為,那系統(tǒng)資源消耗可有多大?。?/p>
針對select模型的缺點(diǎn),epoll模型被提出來了!