乳房太大必要时要缩小_美美生活馆

linux 2.6内核epoll用法举例说明

08月 29th, 2008 by Skylin

epoll用到的所有函数都是在头文件sys/epoll.

h中声明的,下面简要说明所用到的数据结构和函数: 
所用到的数据结构

 
  1. typedef union epoll_data {   
  2.                 void *ptr;   
  3.                 int fd;   
  4.                 __uint32_t u32;   
  5.                 __uint64_t u64;   
  6.         } epoll_data_t;   
  7.    
  8.         struct epoll_event {   
  9.                 __uint32_t events;      /* Epoll events */   
  10.                 epoll_data_t data;      /* User data variable */   
  11.         };   

结构体epoll_event 被用于注册所感兴趣的事件和回传所发生待处理的事件,其中epoll_data 联合体用来保存触发事件的某个文件描述符相关的数据,例如一个client连接到服务器,服务器通过调用accept函数可以得到于这个client对应 的socket文件描述符,可以把这文件描述符赋给epoll_data的fd字段以便后面的读写操作在这个文件描述符上进行。epoll_event 结构体的events字段是表示感兴趣的事件和被触发的事件可能的取值为:EPOLLIN :表示对应的文件描述符可以读; 


EPOLLOUT:表示对应的文件描述符可以写;

 
EPOLLPRI:表示对应的文件描述符有紧急的数据可读(
我不太明白是什么意思,可能是类似client关闭  socket连接这样的事件); 


EPOLLERR:表示对应的文件描述符发生错误; 


EPOLLHUP:表示对应的文件描述符被挂断; 


EPOLLET:表示对应的文件描述符有事件发生; 


所用到的函数: 


1、epoll_create函数 
   函数声明:int epoll_create(int size) 
   该函数生成一个epoll专用的文件描述符,
其中的参数是指定生成描述符的最大范围(我觉得这个参数和select函数的第一个参数应该是类似的但是该怎么设置才好,我也不太清楚)。

 
2、epoll_ctl函数 
   函数声明:int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) 
   该函数用于控制某个文件描述符上的事件,可以注册事件,
修改事件,删除事件。 
   参数:

   epfd:由 epoll_create 生成的epoll专用的文件描述符; 
   op:要进行的操作例如注册事件,可能的取值EPOLL_
CTL_ADD 注册、EPOLL_CTL_MOD 修改、EPOLL_CTL_DEL 删除 
   fd:关联的文件描述符; 
   event:指向epoll_event的指针; 
   如果调用成功返回0,不成功返回-1 


3、epoll_wait函数 
   函数声明:int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int  timeout) 
   该函数用于轮询I/O事件的发生; 
   参数: 

   epfd:由epoll_create 生成的epoll专用的文件描述符; 
   epoll_event:用于回传代处理事件的数组; 
   maxevents:每次能处理的事件数; 
   timeout:等待I/O事件发生的超时值; 
   返回发生事件数。 


例子:

 

 
  1. #include <iostream>   
  2.    
  3. #include <sys/socket.h>   
  4.    
  5. #include <sys/epoll.h>   
  6.    
  7. #include <netinet/in.h>   
  8.    
  9. #include <arpa/inet.h>   
  10.    
  11. #include <fcntl.h>   
  12.    
  13. #include <unistd.h>   
  14.    
  15. #include <stdio.h>   
  16.    
  17.    
  18.    
  19. #define MAXLINE 10   
  20.    
  21. #define OPEN_MAX 100   
  22.    
  23. #define LISTENQ 20   
  24.    
  25. #define SERV_PORT 5555   
  26.    
  27. #define INFTIM 1000   
  28.    
  29.    
  30.    
  31. void setnonblocking(int sock)   
  32.    
  33. {   
  34.    
  35.      int opts;   
  36.    
  37.      opts=fcntl(sock,F_GETFL);   
  38.    
  39.      if(opts<0)   
  40.    
  41.      {   
  42.    
  43.           perror("fcntl(sock,GETFL)");   
  44.    
  45.           exit(1);   
  46.    
  47.      }   
  48.    
  49.      opts = opts|O_NONBLOCK;   
  50.    
  51.      if(fcntl(sock,F_SETFL,opts)<0)   
  52.    
  53.      {   
  54.    
  55.           perror("fcntl(sock,SETFL,opts)");   
  56.    
  57.           exit(1);   
  58.    
  59.      }      
  60.    
  61. }   
  62.    
  63.    
  64.    
  65. int main()   
  66.    
  67. {   
  68.    
  69.      int i, maxi, listenfd, connfd, sockfd,epfd,nfds;   
  70.    
  71.      ssize_t n;   
  72.    
  73.      char line[MAXLINE];   
  74.    
  75.      socklen_t clilen;   
  76.    
  77.      //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件   
  78.    
  79.      struct epoll_event ev,events[20];   
  80.    
  81.      //生成用于处理accept的epoll专用的文件描述符   
  82.    
  83.      epfd=epoll_create(256);   
  84.    
  85.    
  86.    
  87.      struct sockaddr_in clientaddr;   
  88.    
  89.      struct sockaddr_in serveraddr;   
  90.    
  91.      listenfd = socket(AF_INET, SOCK_STREAM, 0);   
  92.    
  93.      //把socket设置为非阻塞方式   
  94.    
  95.      setnonblocking(listenfd);   
  96.    
  97.      //设置与要处理的事件相关的文件描述符   
  98.    
  99.      ev.data.fd=listenfd;   
  100.    
  101.      //设置要处理的事件类型   
  102.    
  103.      ev.events=EPOLLIN|EPOLLET;   
  104.    
  105.      //注册epoll事件   
  106.    
  107.      epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);   
  108.    
  109.    
  110.    
  111.      bzero(&serveraddr, sizeof(serveraddr));   
  112.    
  113.      serveraddr.sin_family = AF_INET;   
  114.    
  115.    
  116.    
  117.      char *local_addr="200.200.200.204";   
  118.    
  119.      inet_aton(local_addr,&(serveraddr.sin_addr));//htons(SERV_PORT);   
  120.    
  121.      serveraddr.sin_port=htons(SERV_PORT);   
  122.    
  123.      bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr));   
  124.    
  125.      listen(listenfd, LISTENQ);   
  126.    
  127.    
  128.    
  129.      maxi = 0;   
  130.    
  131.      for ( ; ; ) {   
  132.    
  133.           //等待epoll事件的发生   
  134.    
  135.           nfds=epoll_wait(epfd,events,20,500);   
  136.    
  137.           //处理所发生的所有事件        
  138.    
  139.           for(i=0;i<nfds;++i)   
  140.    
  141.           {   
  142.    
  143.                if(events.data.fd==listenfd)   
  144.    
  145.                {   
  146.    
  147.    
  148.    
  149.                     connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen);   
  150.    
  151.                     if(connfd<0){   
  152.    
  153.                          perror("connfd<0");   
  154.    
  155.                          exit(1);   
  156.    
  157.                     }   
  158.    
  159.                     setnonblocking(connfd);   
  160.    
  161.    
  162.    
  163.                     char *str = inet_ntoa(clientaddr.sin_addr);   
  164.    
  165.                     std::cout<<"connect from "<_u115 ?tr<<std::endl;   
  166.    
  167.                     //设置用于读操作的文件描述符   
  168.    
  169.                     ev.data.fd=connfd;   
  170.    
  171.                     //设置用于注测的读操作事件   
  172.    
  173.                     ev.events=EPOLLIN|EPOLLET;   
  174.    
  175.                     //注册ev   
  176.    
  177.                     epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);   
  178.    
  179.                }   
  180.    
  181.                else if(events.events&EPOLLIN)   
  182.    
  183.                {   
  184.    
  185.                     if ( (sockfd = events.data.fd) < 0) continue;   
  186.    
  187.                     if ( (n = read(sockfd, line, MAXLINE)) < 0) {   
  188.    
  189.                          if (errno == ECONNRESET) {   
  190.    
  191.    
  192.    
  193.                               close(sockfd);   
  194.    
  195.                               events.data.fd = -1;   
  196.    
  197.                          } else   
  198.    
  199.                               std::cout<<"readline error"<<std::endl;   
  200.    
  201.                     } else if (n == 0) {   
  202.    
  203.                          close(sockfd);   
  204.    
  205.                          events.data.fd = -1;   
  206.    
  207.                     }   
  208.    
  209.                     //设置用于写操作的文件描述符   
  210.    
  211.                     ev.data.fd=sockfd;   
  212.    
  213.                     //设置用于注测的写操作事件   
  214.    
  215.                     ev.events=EPOLLOUT|EPOLLET;   
  216.    
  217.                     //修改sockfd上要处理的事件为EPOLLOUT   
  218.    
  219.                     epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);   
  220.    
  221.                }   
  222.    
  223.                else if(events.events&EPOLLOUT)   
  224.    
  225.                {      
  226.    
  227.                     sockfd = events.data.fd;   
  228.    
  229.                     write(sockfd, line, n);   
  230.    
  231.                     //设置用于读操作的文件描述符   
  232.    
  233.                     ev.data.fd=sockfd;   
  234.    
  235.                     //设置用于注测的读操作事件   
  236.    
  237.                     ev.events=EPOLLIN|EPOLLET;   
  238.    
  239.                     //修改sockfd上要处理的事件为EPOLIN   
  240.    
  241.                     epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);   
  242.    
  243.                }   
  244.    
  245.    
  246.    
  247.           }   
  248.    
  249.    
  250.    
  251.      }   
  252.    
  253. }  

 

Posted in C/C++ |

Leave a Comment