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     }
相關文章
相關標籤/搜索