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 ",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 }