IO复用之epoll

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     }
相关文章
相关标签/搜索