epoll是Linux內核爲處理大批量文件描述符而做了改進的poll,是Linux下多路複用IO接口select/poll的加強版本,它能顯著提升程序在大量併發鏈接中只有少許活躍的狀況下的系統CPU利用率。另外一點緣由就是獲取事件的時候,它無須遍歷整個被偵聽的描述符集,只要遍歷那些被內核IO事件異步喚醒而加入Ready隊列的描述符集合就好了。epoll除了提供select/poll那種IO事件的水平觸發(Level Triggered)外,還提供了邊緣觸發(Edge Triggered),這就使得用戶空間程序有可能緩存IO狀態,減小epoll_wait/epoll_pwait的調用,提升應用程序效率.緩存
epoll相似於事件機制,有客戶端數據發送過來了,就激活了事件,因此極大的提升了效率,適用於高併發的服務端的開發.併發
epoll也有通常的形式:異步
1 int epofd = 0; //epoll對象 2 int fds = 0; //活躍鏈接對象 3 int i = 0; 4 int er = 0; 5 int sock_fd = 0; 6 int len = 0; 7 8 struct epoll_event event; //epoll事件 9 struct epoll_event events[MAX_NUM]; 10 11 struct sockaddr_in client; 12 13 len = sizeof(struct sockaddr_in); 14 15 epofd = epoll_create(MAX_NUM); //建立epoll對象 16 if(epofd < 0){ 17 perror("epoll建立失敗"); 18 return -1; 19 } 20 21 fcntl(listen_fd,F_SETFL,O_NONBLOCK); //將監聽套接字轉化爲非堵塞的監聽套接字 22 23 event.data.fd = listen_fd; //設置epoll事件 24 event.events = EPOLLIN; 25 26 er = epoll_ctl(epofd,EPOLL_CTL_ADD,listen_fd,&event); //添加epoll事件 27 if(er < 0){ 28 perror("epoll_ctl出錯"); 29 return -1; 30 } 31 32 while(1){ 33 fds = epoll_wait(epofd,events,MAX_NUM,-1); //等待數據鏈接 34 if(fds < 0){ 35 perror("epoll_wait出錯"); 36 continue; 37 } 38 39 for(i = 0;i < fds;i++){ 40 if(events[i].data.fd == listen_fd){ //判斷是不是新聯接 41 sock_fd = accept(listen_fd,(struct sockaddr *)&client,&len); //接受鏈接 42 if(sock_fd < 0){ 43 perror("有客戶端鏈接失敗"); 44 continue; 45 } 46 47 //將鏈接添加到事件中 48 event.data.fd = sock_fd; 49 event.events = EPOLLIN | EPOLLET; 50 epoll_ctl(epofd,EPOLL_CTL_ADD,sock_fd,&event); 51 52 printf("有新鏈接%d\n",sock_fd); 53 54 continue; 55 }else { 56 er = rev_data(events[i].data.fd);//新的數據發送過來了 57 if(er == 0){//客戶端斷開鏈接 58 epoll_ctl(epofd,EPOLL_CTL_DEL,events[i].data.fd,&event);//取消該客戶端的時間監聽 59 close(events[i].data.fd);//關閉套接字 60 continue; 61 } 62 } 63 64 } 65 66 }