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
",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     }
原文地址:https://www.cnblogs.com/CHYI1/p/5496224.html