什麼是epoll epoll是什麼?是為處理⼤大批量控制代碼⽽而作了改進的poll。它⼏幾乎具備了之前所說的⼀一切優點,被公認為linux2.6下效能最好的多路i/o就緒通 知⽅方法。
epoll的相關系統調⽤用 epoll只有epoll_create,epoll_ctl,epoll_wait 3個系統調⽤用。
1. int epoll_create(int size); 建立⼀乙個epoll的控制代碼。⾃自從linux2.6.8之後,size引數是被忽略的。需要注意的是,當建立好 epoll控制代碼後,它就是會佔⽤用⼀乙個fd值,在linux下如果檢視/proc/程序id/fd/,是能夠看到這 個fd的,所以在使⽤用完epoll後,必須調⽤用close()關閉,否則可能導致fd被耗盡。
2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); epoll的事件註冊函式,它不同於select()是在監聽事件時告訴核心要監聽什麼型別的事件,⽽而 是在這⾥裡先註冊要監聽的事件型別。 第⼀乙個引數是epoll_create()的返回值。 第⼆二個參數列⽰示動作,⽤用三個巨集來表⽰示: epoll_ctl_add:註冊新的fd到epfd中
epoll_ctl_mod:修改已經註冊的fd的監聽事件; epoll_ctl_del:從epfd中刪除⼀乙個fd; 第三個引數是需要監聽的fd。 第四個引數是告訴核心需要監聽什麼事,struct epoll_event結構如下:
struct union epoll_data
struct epoll_event
events可以是以下⼏幾個巨集的集合: epollin :表⽰示對應的⽂檔案描述符可以讀(包括對端socket正常關閉); epollout:表⽰示對應的⽂檔案描述符可以寫; epollpri:表⽰示對應的⽂檔案描述符有緊急的資料可讀(這⾥裡應該表⽰示有帶外資料到來); epollerr:表⽰示對應的⽂檔案描述符發⽣生錯誤; epollhup:表⽰示對應的⽂檔案描述符被結束通話; epollet: 將epoll設為邊緣觸發(edge triggered)模式,這是相對於⽔水平觸發(level triggered)來說的。 epolloneshot:只監聽⼀一次事件,當監聽完這次事件之後,如果還需要繼續監聽這個 socket的話,需要再次把這個socket加⼊入到epoll佇列⾥裡
3. int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout); 收集在epoll監控的事件中已經傳送的事件。引數events是分配好的epoll_event結構體陣列, epoll將會把發⽣生的事件賦值到events陣列中(events不可以是空指標,核心只負責把資料復 製到這個events陣列中,不會去幫助我們在⽤使用者態中分配記憶體)。maxevents告之核心這個 events有多⼤大,這個 maxevents的值不能⼤大於建立epoll_create()時的size,引數timeout是超時 時間(毫秒,0會⽴立即返回,-1將不確定,也有說法說是永久阻塞)。如果函式調⽤用成功, 返回對應i/o上已準備好的⽂檔案描述符數⽬目,如返回0表⽰示已超時。
2.底層結構示意圖:
epoll_create:系統建立就緒佇列和紅黑樹
就緒佇列:系統維護用來就緒事件
epoll_ctl:主要是對紅黑樹中插入,刪除,更改要x檔案v事件
epoll_wait :用來等待就緒事件,返回就緒事件的個數
3.以下**
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int statup(char*ip,int port)
struct sockaddr_in local;
local.sin_addr.s_addr=inet_addr(ip);
local.sin_port=htons(port);
socklen_t len=sizeof(local);
int b=bind(sock,(struct sockaddr*)&local,len);
if(b<0)
int l=listen(sock,10);
if(l<0)
return sock;
}typedef
struct fd_buf
fd_buf, *fd_buf_p;
void *malloc_fd_buf(int fd)
temp->fd=fd;
return temp;
}void read_fd(int epfd,fd_buf_p fdp)
if(s>0)
else
if(s==0)
free(fdp); //remenber free,!froget
}}void write_msg(int epfd,fd_buf_p fdp)
int accept_sock(int fd)
printf("get a new connect\n");
return newsock;
}int main(int argc,char* argv)
int listen_sock=statup(argv[1],atoi(argv[2]));
int epfd=epoll_create(256);
if(epfd<0)
struct epoll_event evn;
evn.events=epollin;
evn.data.ptr=malloc_fd_buf(listen_sock);
if(epoll_ctl(epfd, epoll_ctl_add, listen_sock,&evn)<0)
struct epoll_event events[20];
int count;
while(1)
//if is lisent_sock
else
if(fdp->fd!=listen_sock)
//is read
if(events[i].events & epollout)
//is write
}//isn"t listensock
}//for i
//break;
}//deflut
break;
}//switch
}//while
return
0;}
高效能伺服器程式設計之epoll
在linux的網路程式設計中,經常使用多執行緒處理高併發的問題,然而linux系統對執行緒數量是有限制的,更重要的是執行緒的排程有系統開銷的,在客戶端數量龐大時,這將是無法接受的問題 另一種處理高併發的方法是使用select來做事件觸發,select實現中,它是採用輪詢來處理的,輪詢的fd數目越多,...
高效能伺服器 epoll驚群與lighttpd改良
關於高效能server,unix網路程式設計 堪稱經典。根據說明,有如下三種相對高效的模型 模型1 最強 乙個程序中有預先建立多個執行緒都阻塞在accept函式 為了免accept驚群,可以在accept前先thread lock 任何乙個監聽執行緒從accept返回得到乙個socket就自己處理這...
高效能伺服器之select
系統提供select函式來實現多路復 用輸 入 輸出模型。select系統調 用是 用來讓我們的程式監視 多個 檔案控制代碼的狀態變化的。程式會停在select這 裡等待,直到被監視的 檔案控制代碼有 乙個或 多個發 生了狀態改變 int select int nfds,fd set readfds...