select poll 与epoll模型的总结
select()和poll() IO多路復(fù)用模型
select優(yōu)點(diǎn):
1.一次可以等待多個(gè)文件描述符,減少了平均等待時(shí)間
2.客戶越來(lái)越多時(shí),減輕了進(jìn)程調(diào)度的壓力(相較于多進(jìn)程多線程服務(wù)器)
select缺點(diǎn):
1.能監(jiān)聽(tīng)的文件描述符有上限,這個(gè)上限是由fd_set決定的。
2.它返回的只是就緒事件的個(gè)數(shù),要判斷是那個(gè)事件滿足,需要遍歷文件描述符。
3.select監(jiān)聽(tīng)的集合是輸入輸出參數(shù),每次監(jiān)聽(tīng)都需要重新初始化。
4.每次調(diào)用select,都需要把fd集合從用戶態(tài)拷貝到內(nèi)核態(tài),這個(gè)開(kāi)銷在fd很多時(shí)會(huì)很大
5.內(nèi)核采用輪詢(遍歷fd集合)的方式來(lái)檢測(cè)就緒事件,這個(gè)開(kāi)銷在fd很多時(shí)也很大
6.select和poll都只能工作在低效的LT(水平觸發(fā))模式
poll優(yōu)點(diǎn):
1.poll監(jiān)聽(tīng)的文件描述符沒(méi)有最大數(shù)量的限制
2.poll對(duì)于select來(lái)說(shuō)包含了一個(gè)pollfd結(jié)構(gòu),pollfd結(jié)構(gòu)包含了要監(jiān)視的event和發(fā)生的revent,而不像select那樣使用輸入輸出的傳遞方式。所以不需要每次監(jiān)聽(tīng)都初始化
poll缺點(diǎn):
1.數(shù)量過(guò)大以后其效率也會(huì)線性下降。
2.poll和select一樣也是返回就緒事件的個(gè)數(shù),需要遍歷文件描述符來(lái)判斷是那個(gè)事件已經(jīng)就緒,當(dāng)數(shù)量很大時(shí),開(kāi)銷也就很大。
3.select和poll都只能工作在低效的LT(水平觸發(fā))模式
4.每次調(diào)用poll,都需要把pollfd數(shù)組從用戶態(tài)拷貝到內(nèi)核態(tài),這個(gè)開(kāi)銷在fd很多時(shí)會(huì)很大
5.內(nèi)核采用輪詢(遍歷pollfd數(shù)組)的方式來(lái)檢測(cè)就緒事件,這個(gè)開(kāi)銷在fd很多時(shí)也很大
拿select模型為例,假設(shè)我們的服務(wù)器需要支持100萬(wàn)的并發(fā)連接,則在__FD_SETSIZE 為1024的情況下,則我們至少需要開(kāi)辟1k個(gè)進(jìn)程才能實(shí)現(xiàn)100萬(wàn)的并發(fā)連接。除了進(jìn)程間上下文切換的時(shí)間消耗外,從內(nèi)核/用戶空間大量的無(wú)腦內(nèi)存拷貝、數(shù)組輪詢等,是系統(tǒng)難以承受的。因此,基于select模型的服務(wù)器程序,要達(dá)到10萬(wàn)級(jí)別的并發(fā)訪問(wèn),是一個(gè)很難完成的任務(wù)。
因此,該epoll上場(chǎng)了。
epoll IO多路復(fù)用模型實(shí)現(xiàn)機(jī)制
由于epoll的實(shí)現(xiàn)機(jī)制與select/poll機(jī)制完全不同,上面所說(shuō)的?select的缺點(diǎn)在epoll上不復(fù)存在。
設(shè)想一下如下場(chǎng)景:有100萬(wàn)個(gè)客戶端同時(shí)與一個(gè)服務(wù)器進(jìn)程保持著TCP連接。而每一時(shí)刻,通常只有幾百上千個(gè)TCP連接是活躍的(事實(shí)上大部分場(chǎng)景都是這種情況)。如何實(shí)現(xiàn)這樣的高并發(fā)?
在select/poll時(shí)代,服務(wù)器進(jìn)程每次都把這100萬(wàn)個(gè)連接告訴操作系統(tǒng)(從用戶態(tài)復(fù)制句柄數(shù)據(jù)結(jié)構(gòu)到內(nèi)核態(tài)),讓操作系統(tǒng)內(nèi)核去查詢這些套接字上是否有事件發(fā)生,輪詢完后,再將句柄數(shù)據(jù)復(fù)制到用戶態(tài),讓服務(wù)器應(yīng)用程序輪詢處理已發(fā)生的網(wǎng)絡(luò)事件,這一過(guò)程資源消耗較大,因此,select/poll一般只能處理幾千的并發(fā)連接。
epoll的設(shè)計(jì)和實(shí)現(xiàn)與select完全不同。epoll通過(guò)在Linux內(nèi)核中申請(qǐng)一個(gè)簡(jiǎn)易的文件系統(tǒng)(文件系統(tǒng)一般用什么數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)?紅黑樹(shù))。把原先的select/poll調(diào)用分成了3個(gè)部分:
1)調(diào)用epoll_create()建立一個(gè)epoll對(duì)象(在epoll文件系統(tǒng)中為這個(gè)句柄對(duì)象分配資源)
2)調(diào)用epoll_ctl向epoll對(duì)象中添加這100萬(wàn)個(gè)連接的套接字
3)調(diào)用epoll_wait收集發(fā)生的事件的連接
如此一來(lái),要實(shí)現(xiàn)上面說(shuō)是的場(chǎng)景,只需要在進(jìn)程啟動(dòng)時(shí)建立一個(gè)epoll對(duì)象,然后在需要的時(shí)候向這個(gè)epoll對(duì)象中添加或者刪除連接。同時(shí),epoll_wait的效率也非常高,因?yàn)檎{(diào)用epoll_wait時(shí),并沒(méi)有一股腦的向操作系統(tǒng)復(fù)制這100萬(wàn)個(gè)連接的句柄數(shù)據(jù),內(nèi)核也不需要去遍歷全部的連接。
下面來(lái)看看linux內(nèi)核具體的epoll機(jī)制實(shí)現(xiàn)思路。
當(dāng)某一進(jìn)程調(diào)用epoll_create方法時(shí),Linux內(nèi)核會(huì)創(chuàng)建一個(gè)eventpoll結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體中有兩個(gè)成員與epoll的使用方式密切相關(guān)。eventpoll結(jié)構(gòu)體如下所示:
[cpp]?view plaincopy每一個(gè)epoll對(duì)象都有一個(gè)獨(dú)立的eventpoll結(jié)構(gòu)體,用于存放通過(guò)epoll_ctl方法向epoll對(duì)象中添加進(jìn)來(lái)的事件。這些事件都會(huì)掛載在紅黑樹(shù)中,如此,重復(fù)添加的事件就可以通過(guò)紅黑樹(shù)而高效的識(shí)別出來(lái)(紅黑樹(shù)的插入時(shí)間效率是lgn,其中n為樹(shù)的高度)。
而所有添加到epoll中的事件都會(huì)與設(shè)備(網(wǎng)卡)驅(qū)動(dòng)程序建立回調(diào)關(guān)系,也就是說(shuō),當(dāng)相應(yīng)的事件發(fā)生時(shí)會(huì)調(diào)用這個(gè)回調(diào)方法。這個(gè)回調(diào)方法在內(nèi)核中叫ep_poll_callback,它會(huì)將發(fā)生的事件添加到rdlist雙鏈表中。
在epoll中,對(duì)于每一個(gè)事件,都會(huì)建立一個(gè)epitem結(jié)構(gòu)體,如下所示:
[cpp]?view plaincopy當(dāng)調(diào)用epoll_wait檢查是否有事件發(fā)生時(shí),只需要檢查eventpoll對(duì)象中的rdlist雙鏈表中是否有epitem元素即可。如果rdlist不為空,則把發(fā)生的事件復(fù)制到用戶態(tài),同時(shí)將事件數(shù)量返回給用戶。
epoll數(shù)據(jù)結(jié)構(gòu)示意圖
從上面的講解可知:通過(guò)紅黑樹(shù)和雙鏈表數(shù)據(jù)結(jié)構(gòu),并結(jié)合回調(diào)機(jī)制,造就了epoll的高效。
OK,講解完了Epoll的機(jī)理,我們便能很容易掌握epoll的用法了。一句話描述就是:三步曲。
第一步:epoll_create()系統(tǒng)調(diào)用。此調(diào)用返回一個(gè)句柄,之后所有的使用都依靠這個(gè)句柄來(lái)標(biāo)識(shí)。
第二步:epoll_ctl()系統(tǒng)調(diào)用。通過(guò)此調(diào)用向epoll對(duì)象中添加、刪除、修改感興趣的事件,返回0標(biāo)識(shí)成功,返回-1表示失敗。
第三部:epoll_wait()系統(tǒng)調(diào)用。通過(guò)此調(diào)用收集收集在epoll監(jiān)控中已經(jīng)發(fā)生的事件。
epoll優(yōu)點(diǎn):
1.epoll維護(hù)的描述符數(shù)目不受到限制,而且性能不會(huì)隨著描述符數(shù)目的增加而下降。(不需要遍歷整個(gè)文件描述符)
2.epoll先通過(guò)epoll_ctl注冊(cè)一個(gè)描述符到內(nèi)核中,并一直維護(hù)著而不像poll每次操作都將所有要監(jiān)控的描述符傳遞給內(nèi)核
3.在描述符讀寫就緒時(shí),通過(guò)回掉函數(shù)將自己加入就緒隊(duì)列中,之后epoll_wait返回該就緒隊(duì)列,所以用戶不需要遍歷整個(gè)文件描述符判斷哪些事件就緒。性能提升。
4.支持ET高效模式。
poll和select適用于關(guān)心描述符個(gè)數(shù)多的應(yīng)用程序。其中epoll對(duì)于每次只有很少描述符就緒很有優(yōu)勢(shì)(采用回調(diào)機(jī)制監(jiān)測(cè)描述符就緒)。
總結(jié)
以上是生活随笔為你收集整理的select poll 与epoll模型的总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: c++实现单例类(懒汉与饿汉)
- 下一篇: 经典的大数据例题