在Linux Socket伺服器短程式設計時,為了處理大量客戶的連接配接請求,需要使用非阻塞I/O和複用,select、poll和epoll是Linux API提供的I/O複用方式,自從Linux 2.6中加入了epoll之後,在高性能伺服器領域得到廣泛的應用,現在比較出名的nginx就是使用epoll來實作I/O複用支援高并發,目前在高并 發的場景下,nginx越來越收到歡迎。這裡有個文章參考。 Nginx成為全球Top1000網站最受歡迎的Web伺服器
。
據 w3techs 7月 3 日的統計資料表明,在全球 Top 1000 的網站中,有 34.9% 的網站在使用 Nginx,這使得 Nginx 超越了 Apache,成為了高流量網站最信任的 Web 伺服器。下圖是統計資料。

select:
下面是select的函數接口:
int select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
select 函數監視的檔案描述符分3類,分别是writefds、readfds、和exceptfds。調用後select函數會阻塞,直到有描述副就緒(有資料 可讀、可寫、或者有except),或者逾時(timeout指定等待時間,如果立即傳回設為null即可),函數傳回。當select函數傳回後,可以 通過周遊fdset,來找到就緒的描述符。
select目前幾乎在所有的平台上支援,其良好跨平台支援也是它的一個優點。select的一 個缺點在于單個程序能夠監視的檔案描述符的數量存在最大限制,在Linux上一般為1024,可以通過修改宏定義甚至重新編譯核心的方式提升這一限制,但 是這樣也會造成效率的降低。
poll:
int poll (struct pollfd *fds, unsigned int nfds, int timeout);
不同與select使用三個位圖來表示三個fdset的方式,poll使用一個 pollfd的指針實作。
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events to watch */
short revents; /* returned events witnessed */
};
pollfd結構包含了要監視的event和發生的event,不再使用select“參數-值”傳遞的方式。同時,pollfd并沒有最大數量限制(但是數量過大後性能也是會下降)。 和select函數一樣,poll傳回後,需要輪詢pollfd來擷取就緒的描述符。
從上面看,select和poll都需要在傳回後,通過周遊檔案描述符來擷取已經就緒的socket。事實上,同時連接配接的大量用戶端在一時刻可能隻有很少的處于就緒狀态,是以随着監視的描述符數量的增長,其效率也會線性下降。
epoll:
epoll的接口如下:
int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
typedef union epoll_data {
void *ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
} epoll_data_t;
struct epoll_event {
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
主要是epoll_create,epoll_ctl和epoll_wait三個函數。epoll_create函數建立epoll檔案描述符,參數size并不是限制了epoll所能監聽的描述符最大個數,隻是對核心初始配置設定内部資料結構的一個建議。傳回是epoll描述符。-1表示建立失敗。epoll_ctl 控制對指定描述符fd執行op操作,event是與fd關聯的監聽事件。op操作有三種:添加EPOLL_CTL_ADD,删除EPOLL_CTL_DEL,修改EPOLL_CTL_MOD。分别添加、删除和修改對fd的監聽事件。epoll_wait 等待epfd上的io事件,最多傳回maxevents個事件。
在 select/poll中,程序隻有在調用一定的方法後,核心才對所有監視的檔案描述符進行掃描,而epoll事先通過epoll_ctl()來注冊一 個檔案描述符,一旦基于某個檔案描述符就緒時,核心會采用類似callback的回調機制,迅速激活這個檔案描述符,當程序調用epoll_wait() 時便得到通知。
epoll的優點主要是一下幾個方面:
- 監視的描述符數量不受限制,它所支援的FD上限是最大可以打開檔案的數目,這個數字一般遠大于2048,舉個例子,在1GB記憶體的機器上大約是10萬左 右,具體數目可以cat /proc/sys/fs/file-max察看,一般來說這個數目和系統記憶體關系很大。select的最大缺點就是程序打開的fd是有數量限制的。這對 于連接配接數量比較大的伺服器來說根本不能滿足。雖然也可以選擇多程序的解決方案( Apache就是這樣實作的),不過雖然linux上面建立程序的代價比較小,但仍舊是不可忽視的,加上程序間資料同步遠比不上線程間同步的高效,是以也 不是一種完美的方案。
- IO的效率不會随着監視fd的數量的增長而下降。epoll不同于select和poll輪詢的方式,而是通過每個fd定義的回調函數來實作的。隻有就緒的fd才會執行回調函數。
3.支援電平觸發和邊沿觸發(隻告訴程序哪些檔案描述符剛剛變為就緒狀态,它隻說一遍,如果我們沒有采取行動,那麼它将不會再次告知,這種方式稱為邊緣觸發)兩種方式,理論上邊緣觸發的性能要更高一些,但是代碼實作相當複雜。
4.mmap加速核心與使用者空間的資訊傳遞。epoll是通過核心于使用者空間mmap同一塊記憶體,避免了無畏的記憶體拷貝。
原文連結:
http://www.cnblogs.com/bigwangdi/p/3182958.html其他相關文章: