現(xiàn)如今,,網(wǎng)絡(luò)通訊中用epoll(linux)和IOCP(windows)幾乎是大家津津樂道的東西,,不為別的,就因為高效,,所以大家喜歡用,。IOCP的基礎(chǔ)東西已經(jīng)講過了,可翻閱《IOCP淺析》 《IOCP淺析[二]——IOCP出現(xiàn)的意義和函數(shù)接口》. 什么是epoll,?epoll是Linux下多路復(fù)用IO接口select/poll的增強(qiáng)版本,,它能顯著提高程序在大量并發(fā)連接中只有少量活躍的情況下的系統(tǒng)CPU利用率,因為它會復(fù)用文件描述符集 合來傳遞結(jié)果而不用迫使開發(fā)者每次等待事件之前都必須重新準(zhǔn)備要被偵聽的文件描述符集合,,另一點原因就是獲取事件的時候,,它無須遍歷整個被偵聽的描述符 集,只要遍歷那些被內(nèi)核IO事件異步喚醒而加入Ready隊列的描述符集合就行了,。epoll除了提供select/poll那種IO事件的電平觸發(fā) (Level Triggered)外,,還提供了邊沿觸發(fā)(Edge Triggered),這就使得用戶空間程序有可能緩存IO狀態(tài),,減少epoll_wait/epoll_pwait的調(diào)用,,提高應(yīng)用程序效率。Linux2.6內(nèi)核中對/dev/epoll設(shè)備的訪問的封裝(system epoll),。 這個使我們開發(fā)網(wǎng)絡(luò)應(yīng)用程序更加簡單,,并且更加高效,。 為什么要使用epoll?同樣,,我們在linux系統(tǒng)下,,影響效率的依然是I/O操作,linux提供給我們select/poll/epoll等多路復(fù)用I/O方式(kqueue暫時沒研究過),,為什么我們對epoll情有獨鐘呢,?原因如下: 1.文件描述符數(shù)量的對比。 epoll并沒有fd(文件描述符)的上限,,它只跟系統(tǒng)內(nèi)存有關(guān),,我的2G的ubuntu下查看是20480個,輕松支持20W個fd,。可使用如下命令查看: cat /proc/sys/fs/file-max 再來看select/poll,,有一個限定的fd的數(shù)量,,linux/posix_types.h頭文件中 #define __FD_SETSIZE 1024 2.效率對比。 當(dāng)然了,,你可以修改上述值,,然后重新編譯內(nèi)核,然后再次寫代碼,,這也是沒問題的,,不過我先說說select/poll的機(jī)制,估計你馬上會作廢上面修改枚舉值的想法,。 select/poll會因為監(jiān)聽fd的數(shù)量而導(dǎo)致效率低下,,因為它是輪詢所有fd,有數(shù)據(jù)就處理,,沒數(shù)據(jù)就跳過,,所以fd的數(shù)量會降低效率;而epoll只處理就緒的fd,,它有一個就緒設(shè)備的隊列,,每次只輪詢該隊列的數(shù)據(jù),然后進(jìn)行處理,。(先簡單講一下,,第二篇還會詳細(xì)講解) 3.內(nèi)存處理方式對比。 不管是哪種I/O機(jī)制,,都無法避免fd在操作過程中拷貝的問題,,而epoll使用了mmap(是指文件/對象的內(nèi)存映射,被映射到多個內(nèi)存頁上),,所以同一塊內(nèi)存就可以避免這個問題,。 btw:TCP/IP協(xié)議棧使用內(nèi)存池管理sk_buff結(jié)構(gòu),,你還可以通過修改內(nèi)存池pool的大小,畢竟linux支持各種微調(diào)內(nèi)核,。 epoll的工作方式epoll分為兩種工作方式LT和ET,。 LT(level triggered) 是默認(rèn)/缺省的工作方式,同時支持 block和no_block socket,。這種工作方式下,,內(nèi)核會通知你一個fd是否就緒,然后才可以對這個就緒的fd進(jìn)行I/O操作,。就算你沒有任何操作,,系統(tǒng)還是會繼續(xù)提示fd已經(jīng)就緒,不過這種工作方式出錯會比較小,,傳統(tǒng)的select/poll就是這種工作方式的代表,。 ET(edge-triggered) 是高速工作方式,僅支持no_block socket,,這種工作方式下,,當(dāng)fd從未就緒變?yōu)榫途w時,內(nèi)核會通知fd已經(jīng)就緒,,并且內(nèi)核認(rèn)為你知道該fd已經(jīng)就緒,,不會再次通知了,除非因為某些操作導(dǎo)致fd就緒狀態(tài)發(fā)生變化,。如果一直不對這個fd進(jìn)行I/O操作,,導(dǎo)致fd變?yōu)槲淳途w時,內(nèi)核同樣不會發(fā)送更多的通知,,因為only once,。所以這種方式下,出錯率比較高,,需要增加一些檢測程序,。 LT可以理解為水平觸發(fā),只要有數(shù)據(jù)可以讀,,不管怎樣都會通知,。而ET為邊緣觸發(fā),只有狀態(tài)發(fā)生變化時才會通知,,可以理解為電平變化,。 如何使用epoll?使用epoll很簡單,,只需要 #include <sys/epoll.h> 有三個關(guān)鍵函數(shù): int epoll_create(int size); int epoll_ctl(int epfd, int op, int fd, struct epoll_events* event); int epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout); 當(dāng)然了,,不要忘記關(guān)閉函數(shù).
============分割線============== 這篇就講到這里了,下面兩篇主要是函數(shù)介紹,,效率分析,,例子,。 轉(zhuǎn)載請注明:C++愛好者博客 ? 淺析epoll-為何多路復(fù)用I/O要使用epoll |
|