织梦CMS - 轻松建站从此开始!

罗索

linux 2.6内核epoll用法

落鹤生 发布于 2011-07-05 14:52 点击:次 
结构体epoll_event 被用于注册所感兴趣的事件和回传所发生待处理的事件,其中epoll_data 联合体用来保存触发事件的某个文件描述符相关的数据
TAG:

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;      
  10. epoll_data_t data;      
  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. #include <sys/socket.h> 
  3. #include <sys/epoll.h> 
  4. #include <netinet/in.h> 
  5. #include <arpa/inet.h> 
  6. #include <fcntl.h> 
  7. #include <unistd.h> 
  8. #include <stdio.h> 
  9.   
  10. #define MAXLINE 10 
  11. #define OPEN_MAX 100 
  12. #define LISTENQ 20 
  13. #define SERV_PORT 5555 
  14. #define INFTIM 1000 
  15.   
  16. void setnonblocking(int sock) 
  17.      int opts; 
  18.      opts=fcntl(sock,F_GETFL); 
  19.      if(opts<0) 
  20.      { 
  21.           perror("fcntl(sock,GETFL)"); 
  22.           exit(1); 
  23.      } 
  24.      opts = opts|O_NONBLOCK; 
  25.      if(fcntl(sock,F_SETFL,opts)<0) 
  26.      { 
  27.           perror("fcntl(sock,SETFL,opts)"); 
  28.           exit(1); 
  29.      }    
  30.  
  31. int main() 
  32.      int i, maxi, listenfd, connfd, sockfd,epfd,nfds; 
  33.      ssize_t n; 
  34.      char line[MAXLINE]; 
  35.      socklen_t clilen; 
  36.      //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件 
  37.      struct epoll_event ev,events[20]; 
  38.      //生成用于处理accept的epoll专用的文件描述符 
  39.      epfd=epoll_create(256); 
  40.   
  41.      struct sockaddr_in clientaddr; 
  42.      struct sockaddr_in serveraddr; 
  43.      listenfd = socket(AF_INET, SOCK_STREAM, 0); 
  44.  
  45.      //把socket设置为非阻塞方式 
  46.      setnonblocking(listenfd); 
  47.      //设置与要处理的事件相关的文件描述符 
  48.      ev.data.fd=listenfd; 
  49.      //设置要处理的事件类型 
  50.      ev.events=EPOLLIN|EPOLLET; 
  51.      //注册epoll事件 
  52.      epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev); 
  53.      bzero(&serveraddr, sizeof(serveraddr)); 
  54.      serveraddr.sin_family = AF_INET; 
  55.   
  56.      char *local_addr="200.200.200.204"
  57.      inet_aton(local_addr,&(serveraddr.sin_addr));//htons(SERV_PORT); 
  58.      serveraddr.sin_port=htons(SERV_PORT); 
  59.      bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr)); 
  60.      listen(listenfd, LISTENQ); 
  61.  
  62.      maxi = 0; 
  63.      for ( ; ; ) { 
  64.           //等待epoll事件的发生 
  65.           nfds=epoll_wait(epfd,events,20,500); 
  66.           //处理所发生的所有事件      
  67.           for(i=0;i<nfds;++i) 
  68.           { 
  69.                if(events[i].data.fd==listenfd) 
  70.                { 
  71.                     connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen); 
  72.                     if(connfd<0){ 
  73.                          perror("connfd<0"); 
  74.                          exit(1); 
  75.                     } 
  76.                     setnonblocking(connfd); 
  77.   
  78.                     char *str = inet_ntoa(clientaddr.sin_addr); 
  79.                     std::cout<<"connect from "<_u115 ?tr<<std::endl; 
  80.                     //设置用于读操作的文件描述符 
  81.                     ev.data.fd=connfd; 
  82.                     //设置用于注测的读操作事件 
  83.                     ev.events=EPOLLIN|EPOLLET; 
  84.                     //注册ev 
  85.               epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev); 
  86.                } 
  87.                else if(events[i].events&EPOLLIN) 
  88.                { 
  89.                     if ( (sockfd = events[i].data.fd) < 0) continue
  90.                     if ( (n = read(sockfd, line, MAXLINE)) < 0) { 
  91.                          if (errno == ECONNRESET) { 
  92.                               close(sockfd); 
  93.                               events[i].data.fd = -1; 
  94.                          } else 
  95.                               std::cout<<"readline error"<<std::endl; 
  96.                     } else if (n == 0) { 
  97.                          close(sockfd); 
  98.                          events[i].data.fd = -1; 
  99.                     } 
  100.                     //设置用于写操作的文件描述符 
  101.                     ev.data.fd=sockfd; 
  102.                     //设置用于注测的写操作事件 
  103.                     ev.events=EPOLLOUT|EPOLLET; 
  104.                     //修改sockfd上要处理的事件为EPOLLOUT 
  105.                 epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); 
  106.                } 
  107.                else if(events[i].events&EPOLLOUT) 
  108.                {    
  109.                     sockfd = events[i].data.fd; 
  110.                     write(sockfd, line, n); 
  111.                     //设置用于读操作的文件描述符 
  112.                     ev.data.fd=sockfd; 
  113.                     //设置用于注测的读操作事件 
  114.                     ev.events=EPOLLIN|EPOLLET; 
  115.                     //修改sockfd上要处理的事件为EPOLIN 
  116.                 epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); 
  117.                } 
  118.           } 
  119.      } 
(xxwei)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201107/14660.html]
本文出处:blog.sina.com.cn/xxwei 作者:xxwei
顶一下
(4)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容