epoll是Linux核心為處理大批量檔案描述符而作了改進的poll,是Linux下多路復用IO接口select/poll的增強版本,它能顯著提高程式在大量並發連線中只有少量活躍的情況下的系統CPU利用率。另一點原因就是獲取事件的時候,它無須遍歷整個被偵聽的描述符集,只要遍歷那些被核心IO事件異步喚醒而加入Ready佇列的描述符集合就行了。epoll除了提供select/poll那種IO事件的水平觸發(Level Triggered)外,還提供了邊緣觸發(Edge Triggered),這就使得用戶空間程式有可能快取IO狀態,減少epoll_wait/epoll_pwait的調用,提高應用程式效率。
基本介紹
- 外文名:epoll
- 優點:核心微調等
- 工作方式:LT和ET
- 系統調用:epoll_create, epoll_ctl等
優點
使用epoll進行高性能網路編程核心微調
使用
系統調用
nfds=epoll_wait(kdpfd,events,maxevents,-1);
int epfd = epoll_create(POLL_SIZE); struct epoll_event ev* = NULL; struct epoll_event events; nfds = epoll_wait(epfd, events, 20, 500); { for (n = 0; n < nfds; ++n) { if (events[n].data.fd == listener) { //如果是主socket的事件的話,則表示 //有新連線進入了,進行新連線的處理。 client = accept(listener, (structsockaddr *)&local, &addrlen); if (client < 0) { perror("accept"); continue; } setnonblocking(client); //將新連線置於非阻塞模式 ev.events = EPOLLIN | EPOLLET; //並且將新連線也加入EPOLL的監聽佇列。 //注意,這裡的參數EPOLLIN|EPOLLET並沒有設定對寫socket的監聽, //如果有寫操作的話,這個時候epoll是不會返回事件的,如果要對寫操作 //也監聽的話,應該是EPOLLIN|EPOLLOUT|EPOLLET ev.data.fd = client; if (epoll_ctl(epfd, EPOLL_CTL_ADD, client, &ev) < 0) { //設定好event之後,將這個新的event通過epoll_ctl加入到epoll的監聽佇列裡面, //這裡用EPOLL_CTL_ADD來加一個新的epoll事件,通過EPOLL_CTL_DEL來減少一個 //epoll事件,通過EPOLL_CTL_MOD來改變一個事件的監聽方式。 fprintf(stderr, "epollsetinsertionerror:fd=%d", client); return -1; } } else if(event[n].events & EPOLLIN) { //如果是已經連線的用戶,並且收到數據, //那么進行讀入 int sockfd_r; if ((sockfd_r = event[n].data.fd) < 0) continue; read(sockfd_r, buffer, MAXSIZE); //修改sockfd_r上要處理的事件為EPOLLOUT ev.data.fd = sockfd_r; ev.events = EPOLLOUT | EPOLLET; epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd_r, &ev) } else if(event[n].events & EPOLLOUT) { //如果有數據傳送 int sockfd_w = events[n].data.fd; write(sockfd_w, buffer, sizeof(buffer)); //修改sockfd_w上要處理的事件為EPOLLIN ev.data.fd = sockfd_w; ev.events = EPOLLIN | EPOLLET; epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd_w, &ev) } do_use_fd(events[n].data.fd); } }
