Epoll 是一種高效的管理socket的模型,相對於select和poll更加高效。數組
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 / };
(1) epoll_data 聯合體用來保存觸發事件的某個文件描述符相關的數據.數據結構
(2) epoll_event 結構體的events字段是表示感興趣的事件和被觸發的事件:socket
EPOLLIN :表示對應的文件描述符能夠讀; EPOLLOUT:表示對應的文件描述符能夠寫; EPOLLPRI:表示對應的文件描述符有緊急的數據可讀 EPOLLERR:表示對應的文件描述符發生錯誤; EPOLLHUP:表示對應的文件描述符被掛斷; EPOLLET:表示對應的文件描述符設定爲edge模式
*epoll_create, epoll_create1 函數
函數聲明:int epoll_create(int size)
該函數生成一個epoll專用的文件描述符,其中的參數是指定生成描述符的最大範圍。函數
函數聲明:int epoll_ctl(int epfd, int op, int fd, struct epoll_event event) 該函數用於控制某個文件描述符上的事件,能夠註冊事件,修改事件,刪除事件。
參數:epfd:由 epoll_create 生成的epoll專用的文件描述符;
op:要進行的操做例如註冊事件:ui
EPOLL_CTL_ADD 註冊、 EPOLL_CTL_MOD 修改、 EPOLL_CTL_DEL 刪除
int main() { //聲明epoll_event結構體的變量,ev用於註冊事件,數組用於回傳要處理的事件 struct epoll_event ev,events[20]; epfd=epoll_create(10000); //建立epoll句柄 listenfd = socket(AF_INET, SOCK_STREAM, 0); //把socket設置爲非阻塞方式 setnonblocking(listenfd); bzero(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = INADDR_ANY; serveraddr.sin_port=htons(SERV_PORT); bind(listenfd,(struct sockaddr )&serveraddr, sizeof(serveraddr)); listen(listenfd, 255); //設置與要處理的事件相關的文件描述符 ev.data.fd=listenfd; //設置要處理的事件類型 ev.events=EPOLLIN; //註冊epoll事件 epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev); for ( ; ; ) { //等待epoll事件的發生 nfds=epoll_wait(epfd,events,20,1000); //處理所發生的全部事件 for(i=0;i<nfds;++i) { if(events .data.fd==listenfd) { connfd = accept(listenfd,(struct sockaddr )&clientaddr, &clilen); if(connfd<0) { perror("connfd<0"); } setnonblocking(connfd); //設置用於讀操做的文件描述符 ev.data.fd=connfd; //設置用於注測的讀操做事件 ev.events=EPOLLIN|EPOLLET; //註冊event epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev); } else if(events .events&EPOLLIN) { read_socket(events .data.fd); ev.data.fd=events .data.fd; ev.events=EPOLLIN|EPOLLOUT|EPOLLET; epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); } else if(events .events&EPOLLOUT) { write_socket(events .data.fd); ev.data.fd=events .data.fd; ev.events=EPOLLIN|EPOLLET; //ET模式 epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); } else { perror("other event"); } } } }